VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp@ 25623

Last change on this file since 25623 was 25623, checked in by vboxsync, 15 years ago

more cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 18.8 KB
Line 
1/* $Id: tstRTLockValidator.cpp 25623 2010-01-03 13:59:05Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTLockValidator.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/lockvalidator.h>
36
37#include <iprt/asm.h> /* for return addresses */
38#include <iprt/critsect.h>
39#include <iprt/err.h>
40#include <iprt/semaphore.h>
41#include <iprt/test.h>
42#include <iprt/thread.h>
43#include <iprt/time.h>
44
45
46/*******************************************************************************
47* Global Variables *
48*******************************************************************************/
49/** The testcase handle. */
50static RTTEST g_hTest;
51/** Flip this in the debugger to get some peace to single step wild code. */
52bool volatile g_fDoNotSpin = false;
53
54static uint32_t g_cThreads;
55static uint32_t g_iDeadlockThread;
56static RTTHREAD g_ahThreads[32];
57static RTCRITSECT g_aCritSects[32];
58static RTSEMRW g_ahSemRWs[32];
59
60/** When to stop testing. */
61static uint64_t g_NanoTSStop;
62/** The number of deadlocks. */
63static uint32_t volatile g_cDeadlocks;
64/** The number of loops. */
65static uint32_t volatile g_cLoops;
66
67
68/**
69 * Spin until someone else has taken ownership of the critical section.
70 *
71 * @returns true on success, false on abort.
72 * @param pCritSect The critical section.
73 */
74static bool testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)
75{
76 unsigned iLoop = 0;
77 while (!RTCritSectIsOwned(pCritSect))
78 {
79 if (!RTCritSectIsInitialized(pCritSect))
80 return false;
81 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
82 iLoop++;
83 }
84 return true;
85}
86
87
88/**
89 * Spin until someone else has taken ownership (any kind) of the read-write
90 * semaphore.
91 *
92 * @returns true on success, false on abort.
93 * @param hSemRW The read-write semaphore.
94 */
95static bool testWaitForSemRWToBeOwned(RTSEMRW hSemRW)
96{
97 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
98 unsigned iLoop = 0;
99 for (;;)
100 {
101 if (RTSemRWGetWriteRecursion(hSemRW) > 0)
102 return true;
103 if (RTSemRWGetReadCount(hSemRW) > 0)
104 return true;
105 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
106 iLoop++;
107 }
108 return true;
109}
110
111
112/**
113 * Waits for a thread to enter a sleeping state.
114 *
115 * @returns true on success, false on abort.
116 * @param hThread The thread.
117 * @param enmDesiredState The desired thread sleep state.
118 * @param pvLock The lock it should be sleeping on.
119 */
120static bool testWaitForThreadToSleep(RTTHREAD hThread, RTTHREADSTATE enmDesiredState, void *pvLock)
121{
122 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
123 for (unsigned iLoop = 0; ; iLoop++)
124 {
125 RTTHREADSTATE enmState = RTThreadGetState(hThread);
126 if (RTTHREAD_IS_SLEEPING(enmState))
127 {
128 if ( enmState == enmDesiredState
129 && ( !pvLock
130 || ( pvLock == RTLockValidatorQueryBlocking(hThread)
131 && !RTLockValidatorIsBlockedThreadInValidator(hThread) )
132 )
133 )
134 return true;
135 }
136 else if ( enmState != RTTHREADSTATE_RUNNING
137 && enmState != RTTHREADSTATE_INITIALIZING)
138 return false;
139 RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
140 }
141}
142
143
144/**
145 * Waits for all the other threads to enter sleeping states.
146 *
147 * @returns VINF_SUCCESS on success, VERR_INTERNAL_ERROR on failure.
148 * @param enmDesiredState The desired thread sleep state.
149 * @param cWaitOn The distance to the lock they'll be waiting on,
150 * the lock type is derived from the desired state.
151 * UINT32_MAX means no special lock.
152 */
153static int testWaitForAllOtherThreadsToSleep(RTTHREADSTATE enmDesiredState, uint32_t cWaitOn)
154{
155 RTTHREAD hThreadSelf = RTThreadSelf();
156 for (uint32_t i = 0; i < g_cThreads; i++)
157 {
158 RTTHREAD hThread = g_ahThreads[i];
159 if ( hThread != NIL_RTTHREAD
160 && hThread != hThreadSelf)
161 {
162 void *pvLock = NULL;
163 if (cWaitOn != UINT32_MAX)
164 {
165 uint32_t j = (i + cWaitOn) % g_cThreads;
166 switch (enmDesiredState)
167 {
168 case RTTHREADSTATE_CRITSECT: pvLock = &g_aCritSects[j]; break;
169 case RTTHREADSTATE_RW_WRITE:
170 case RTTHREADSTATE_RW_READ: pvLock = g_ahSemRWs[j]; break;
171 default: break;
172 }
173 }
174 bool fRet = testWaitForThreadToSleep(hThread, enmDesiredState, pvLock);
175 if (!fRet)
176 return VERR_INTERNAL_ERROR;
177 }
178 }
179 RTThreadSleep(4); /* fudge factor */
180 return VINF_SUCCESS;
181}
182
183
184/**
185 * Worker that starts the threads.
186 *
187 * @returns Same as RTThreadCreate.
188 * @param cThreads The number of threads to start.
189 * @param pfnThread Thread function.
190 */
191static int testStartThreads(uint32_t cThreads, PFNRTTHREAD pfnThread)
192{
193 uint32_t i;
194 for (i = 0; i < RT_ELEMENTS(g_ahThreads); i++)
195 g_ahThreads[i] = NIL_RTTHREAD;
196
197 for (i = 0; i < cThreads; i++)
198 RTTEST_CHECK_RC_OK_RET(g_hTest,
199 RTThreadCreateF(&g_ahThreads[i], pfnThread, (void *)(uintptr_t)i, 0,
200 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "thread-%02u", i),
201 rcCheck);
202 return VINF_SUCCESS;
203}
204
205
206/**
207 * Worker that waits for the threads to complete.
208 *
209 * @param cMillies How long to wait for each.
210 * @param fStopOnError Whether to stop on error and heed the thread
211 * return status.
212 */
213static void testWaitForThreads(uint32_t cMillies, bool fStopOnError)
214{
215 uint32_t i = RT_ELEMENTS(g_ahThreads);
216 while (i-- > 0)
217 if (g_ahThreads[i] != NIL_RTTHREAD)
218 {
219 int rcThread;
220 int rc2;
221 RTTEST_CHECK_RC_OK(g_hTest, rc2 = RTThreadWait(g_ahThreads[i], cMillies, &rcThread));
222 if (RT_SUCCESS(rc2))
223 g_ahThreads[i] = NIL_RTTHREAD;
224 if (fStopOnError && (RT_FAILURE(rc2) || RT_FAILURE(rcThread)))
225 return;
226 }
227}
228
229
230static DECLCALLBACK(int) test1Thread(RTTHREAD ThreadSelf, void *pvUser)
231{
232 uintptr_t i = (uintptr_t)pvUser;
233 PRTCRITSECT pMine = &g_aCritSects[i];
234 PRTCRITSECT pNext = &g_aCritSects[(i + 1) % g_cThreads];
235
236 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS, rcCheck);
237 if (i & 1)
238 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
239 if (testWaitForCritSectToBeOwned(pNext))
240 {
241 int rc;
242 if (i != g_iDeadlockThread)
243 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
244 else
245 {
246 RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_CRITSECT, 1));
247 if (RT_SUCCESS(rc))
248 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VERR_SEM_LV_DEADLOCK);
249 }
250 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
251 if (RT_SUCCESS(rc))
252 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(pNext), VINF_SUCCESS);
253 }
254 if (i & 1)
255 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS);
256 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS);
257 return VINF_SUCCESS;
258}
259
260
261static DECLCALLBACK(int) test2Thread(RTTHREAD ThreadSelf, void *pvUser)
262{
263 uintptr_t i = (uintptr_t)pvUser;
264 RTSEMRW hMine = g_ahSemRWs[i];
265 RTSEMRW hNext = g_ahSemRWs[(i + 1) % g_cThreads];
266 int rc;
267
268 if (i & 1)
269 {
270 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestWrite(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
271 if ((i & 3) == 3)
272 RTTEST_CHECK_RC(g_hTest, RTSemRWRequestWrite(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS);
273 }
274 else
275 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
276 if (testWaitForSemRWToBeOwned(hNext))
277 {
278 if (i != g_iDeadlockThread)
279 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
280 else
281 {
282 RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_RW_WRITE, 1));
283 if (RT_SUCCESS(rc))
284 {
285 if (g_cThreads > 1)
286 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_DEADLOCK);
287 else
288 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_ILLEGAL_UPGRADE);
289 }
290 }
291 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
292 if (RT_SUCCESS(rc))
293 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hNext), VINF_SUCCESS);
294 }
295 if (i & 1)
296 {
297 if ((i & 3) == 3)
298 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hMine), VINF_SUCCESS);
299 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hMine), VINF_SUCCESS);
300 }
301 else
302 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseRead(hMine), VINF_SUCCESS);
303 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
304 return VINF_SUCCESS;
305}
306
307
308static DECLCALLBACK(int) test3Thread(RTTHREAD ThreadSelf, void *pvUser)
309{
310 uintptr_t i = (uintptr_t)pvUser;
311 RTSEMRW hMine = g_ahSemRWs[i];
312 RTSEMRW hNext = g_ahSemRWs[(i + 1) % g_cThreads];
313 int rc;
314
315 if (i & 1)
316 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestWrite(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
317 else
318 RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
319 if (testWaitForSemRWToBeOwned(hNext))
320 {
321 do
322 {
323 rc = RTSemRWRequestWrite(hNext, 60*1000);
324 if (rc != VINF_SUCCESS && rc != VERR_SEM_LV_DEADLOCK && rc != VERR_SEM_LV_ILLEGAL_UPGRADE)
325 {
326 RTTestFailed(g_hTest, "#%u: RTSemRWRequestWrite -> %Rrc\n", i, rc);
327 break;
328 }
329 if (RT_SUCCESS(rc))
330 {
331 RTTEST_CHECK_RC(g_hTest, rc = RTSemRWReleaseWrite(hNext), VINF_SUCCESS);
332 if (RT_FAILURE(rc))
333 break;
334 }
335 else
336 ASMAtomicIncU32(&g_cDeadlocks);
337 ASMAtomicIncU32(&g_cLoops);
338 } while (RTTimeNanoTS() < g_NanoTSStop);
339 }
340 if (i & 1)
341 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hMine), VINF_SUCCESS);
342 else
343 RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseRead(hMine), VINF_SUCCESS);
344 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
345 return VINF_SUCCESS;
346}
347
348
349static DECLCALLBACK(int) test4Thread(RTTHREAD ThreadSelf, void *pvUser)
350{
351 uintptr_t i = (uintptr_t)pvUser;
352 RTSEMRW hMine = g_ahSemRWs[i];
353 RTSEMRW hNext = g_ahSemRWs[(i + 1) % g_cThreads];
354
355 do
356 {
357 int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, 60*1000); /* ugly ;-) */
358 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
359 if (rc1 != VINF_SUCCESS && rc1 != VERR_SEM_LV_DEADLOCK && rc1 != VERR_SEM_LV_ILLEGAL_UPGRADE)
360 {
361 RTTestFailed(g_hTest, "#%u: RTSemRWRequest%s(hMine,) -> %Rrc\n", i, i & 1 ? "Write" : "read", rc1);
362 break;
363 }
364 if (RT_SUCCESS(rc1))
365 {
366 for (unsigned iInner = 0; iInner < 4; iInner++)
367 {
368 int rc2 = RTSemRWRequestWrite(hNext, 60*1000);
369 if (rc2 != VINF_SUCCESS && rc2 != VERR_SEM_LV_DEADLOCK && rc2 != VERR_SEM_LV_ILLEGAL_UPGRADE)
370 {
371 RTTestFailed(g_hTest, "#%u: RTSemRWRequestWrite -> %Rrc\n", i, rc2);
372 break;
373 }
374 if (RT_SUCCESS(rc2))
375 {
376 RTTEST_CHECK_RC(g_hTest, rc2 = RTSemRWReleaseWrite(hNext), VINF_SUCCESS);
377 if (RT_FAILURE(rc2))
378 break;
379 }
380 else
381 ASMAtomicIncU32(&g_cDeadlocks);
382 ASMAtomicIncU32(&g_cLoops);
383 }
384
385 RTTEST_CHECK_RC(g_hTest, rc1 = (i & 1 ? RTSemRWReleaseWrite : RTSemRWReleaseRead)(hMine), VINF_SUCCESS);
386 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
387 if (RT_FAILURE(rc1))
388 break;
389 }
390 else
391 ASMAtomicIncU32(&g_cDeadlocks);
392 ASMAtomicIncU32(&g_cLoops);
393 } while (RTTimeNanoTS() < g_NanoTSStop);
394
395 return VINF_SUCCESS;
396}
397
398
399static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName)
400{
401 if (cSecs)
402 RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses);
403 else
404 RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);
405
406 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
407 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads);
408
409 g_cThreads = cThreads;
410
411 for (uint32_t i = 0; i < cThreads; i++)
412 {
413 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS);
414 RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS);
415 }
416
417 uint32_t cLoops = 0;
418 uint32_t cDeadlocks = 0;
419 uint32_t cErrors = RTTestErrorCount(g_hTest);
420 for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
421 {
422 g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
423 g_cLoops = 0;
424 g_cDeadlocks = 0;
425 g_NanoTSStop = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0;
426
427 int rc = testStartThreads(cThreads, pfnThread);
428 if (RT_SUCCESS(rc))
429 testWaitForThreads(30*1000 + cSecs*1000, true);
430
431 RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0);
432 cLoops += g_cLoops;
433 RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0);
434 cDeadlocks += g_cDeadlocks;
435 }
436
437 for (uint32_t i = 0; i < cThreads; i++)
438 {
439 RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
440 RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS);
441 }
442 testWaitForThreads(10*1000, false);
443
444 if (cSecs)
445 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
446 cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
447}
448
449
450static void test1(uint32_t cThreads, uint32_t cPasses)
451{
452 testIt(cThreads, cPasses, 0, test1Thread, "critsect");
453}
454
455
456static void test2(uint32_t cThreads, uint32_t cPasses)
457{
458 testIt(cThreads, cPasses, 0, test2Thread, "read-write");
459}
460
461
462static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
463{
464 testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race");
465}
466
467
468static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
469{
470 testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2");
471}
472
473
474static bool testIsLockValidationCompiledIn(void)
475{
476 RTCRITSECT CritSect;
477 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectInit(&CritSect), false);
478 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectEnter(&CritSect), false);
479 bool fRet = CritSect.pValidatorRec
480 && CritSect.pValidatorRec->hThread == RTThreadSelf();
481 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectLeave(&CritSect), false);
482 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectDelete(&CritSect), false);
483
484 RTSEMRW hSemRW;
485 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWCreate(&hSemRW), false);
486 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWRequestRead(hSemRW, 50), false);
487 int rc = RTSemRWRequestWrite(hSemRW, 1);
488 if (rc != VERR_SEM_LV_ILLEGAL_UPGRADE)
489 fRet = false;
490 RTTEST_CHECK_RET(g_hTest, RT_FAILURE_NP(rc), false);
491 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWReleaseRead(hSemRW), false);
492 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWDestroy(hSemRW), false);
493
494 return fRet;
495}
496
497
498int main()
499{
500 /*
501 * Init.
502 */
503 int rc = RTTestInitAndCreate("tstRTLockValidator", &g_hTest);
504 if (rc)
505 return rc;
506 RTTestBanner(g_hTest);
507
508 RTLockValidatorSetEnabled(true);
509 RTLockValidatorSetMayPanic(false);
510 RTLockValidatorSetQuiet(true);
511 if (!testIsLockValidationCompiledIn())
512 return RTTestErrorCount(g_hTest) > 0
513 ? RTTestSummaryAndDestroy(g_hTest)
514 : RTTestSkipAndDestroy(g_hTest, "deadlock detection is not compiled in");
515 RTLockValidatorSetQuiet(false);
516
517 /*
518 * Some initial tests with verbose output.
519 */
520 test1(3, 1);
521 test2(1, 1);
522 test2(3, 1);
523
524 /*
525 * More thorough testing without noisy output.
526 */
527 RTLockValidatorSetQuiet(true);
528
529 test1( 2, 256); /* 256 * 4ms = 1s (approx); 4ms == fudge factor */
530 test1( 3, 256);
531 test1( 7, 256);
532 test1(10, 256);
533 test1(15, 256);
534 test1(30, 256);
535
536 test2( 1, 256);
537 test2( 2, 256);
538 test2( 3, 256);
539 test2( 7, 256);
540 test2(10, 256);
541 test2(15, 256);
542 test2(30, 256);
543
544 test3( 2, 1, 2);
545 test3(10, 1, 2);
546
547 test4( 2, 1, 2);
548 test4( 6, 1, 2);
549 test4(10, 1, 10);
550 test4(30, 1, 10);
551
552 return RTTestSummaryAndDestroy(g_hTest);
553}
554
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