VirtualBox

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

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

tstRTLockValidator: testcase improvements.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 18.8 KB
Line 
1/* $Id: tstRTLockValidator.cpp 25622 2010-01-03 13:56:34Z 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.215389.xyz. 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 g_iDeadlockThread = cThreads - 1;
411
412 for (uint32_t i = 0; i < cThreads; i++)
413 {
414 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS);
415 RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS);
416 }
417
418 uint32_t cLoops = 0;
419 uint32_t cDeadlocks = 0;
420 uint32_t cErrors = RTTestErrorCount(g_hTest);
421 for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
422 {
423 g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
424 g_cLoops = 0;
425 g_cDeadlocks = 0;
426 g_NanoTSStop = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0;
427
428 int rc = testStartThreads(cThreads, pfnThread);
429 if (RT_SUCCESS(rc))
430 testWaitForThreads(30*1000 + cSecs*1000, true);
431
432 RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0);
433 cLoops += g_cLoops;
434 RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0);
435 cDeadlocks += g_cDeadlocks;
436 }
437
438 for (uint32_t i = 0; i < cThreads; i++)
439 {
440 RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
441 RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS);
442 }
443 testWaitForThreads(10*1000, false);
444
445 if (cSecs)
446 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
447 cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
448}
449
450
451static void test1(uint32_t cThreads, uint32_t cPasses)
452{
453 testIt(cThreads, cPasses, 0, test1Thread, "critsect");
454}
455
456
457static void test2(uint32_t cThreads, uint32_t cPasses)
458{
459 testIt(cThreads, cPasses, 0, test2Thread, "read-write");
460}
461
462
463static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
464{
465 testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race");
466}
467
468
469static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
470{
471 testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2");
472}
473
474
475static bool testIsLockValidationCompiledIn(void)
476{
477 RTCRITSECT CritSect;
478 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectInit(&CritSect), false);
479 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectEnter(&CritSect), false);
480 bool fRet = CritSect.pValidatorRec
481 && CritSect.pValidatorRec->hThread == RTThreadSelf();
482 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectLeave(&CritSect), false);
483 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectDelete(&CritSect), false);
484
485 RTSEMRW hSemRW;
486 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWCreate(&hSemRW), false);
487 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWRequestRead(hSemRW, 50), false);
488 int rc = RTSemRWRequestWrite(hSemRW, 1);
489 if (rc != VERR_SEM_LV_ILLEGAL_UPGRADE)
490 fRet = false;
491 RTTEST_CHECK_RET(g_hTest, RT_FAILURE_NP(rc), false);
492 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWReleaseRead(hSemRW), false);
493 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWDestroy(hSemRW), false);
494
495 return fRet;
496}
497
498
499int main()
500{
501 /*
502 * Init.
503 */
504 int rc = RTTestInitAndCreate("tstRTLockValidator", &g_hTest);
505 if (rc)
506 return rc;
507 RTTestBanner(g_hTest);
508
509 RTLockValidatorSetEnabled(true);
510 RTLockValidatorSetMayPanic(false);
511 RTLockValidatorSetQuiet(true);
512 if (!testIsLockValidationCompiledIn())
513 return RTTestErrorCount(g_hTest) > 0
514 ? RTTestSummaryAndDestroy(g_hTest)
515 : RTTestSkipAndDestroy(g_hTest, "deadlock detection is not compiled in");
516 RTLockValidatorSetQuiet(false);
517
518 /*
519 * Some initial tests with verbose output.
520 */
521 test1(3, 1);
522 test2(1, 1);
523 test2(3, 1);
524
525 /*
526 * More thorough testing without noisy output.
527 */
528 RTLockValidatorSetQuiet(true);
529
530 test1( 2, 256); /* 256 * 4ms = 1s (approx); 4ms == fudge factor */
531 test1( 3, 256);
532 test1( 7, 256);
533 test1(10, 256);
534 test1(15, 256);
535 test1(30, 256);
536
537 test2( 1, 256);
538 test2( 2, 256);
539 test2( 3, 256);
540 test2( 7, 256);
541 test2(10, 256);
542 test2(15, 256);
543 test2(30, 256);
544
545 test3( 2, 1, 2);
546 test3(10, 1, 2);
547
548 test4( 2, 1, 2);
549 test4( 6, 1, 2);
550 test4(10, 1, 10);
551 test4(30, 1, 10);
552
553 return RTTestSummaryAndDestroy(g_hTest);
554}
555
Note: See TracBrowser for help on using the repository browser.

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