VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/test.cpp@ 18538

最後變更 在這個檔案從18538是 18427,由 vboxsync 提交於 16 年 前

iprt/test.cpp: MSC/64 warnings.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 20.8 KB
 
1/* $Id: test.cpp 18427 2009-03-28 01:52:49Z vboxsync $ */
2/** @file
3 * IPRT - Testcase Framework.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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/test.h>
36#include <iprt/mem.h>
37#include <iprt/param.h>
38#include <iprt/string.h>
39#include <iprt/stream.h>
40#include <iprt/critsect.h>
41#include <iprt/once.h>
42#include <iprt/err.h>
43#include <iprt/asm.h>
44
45#include "internal/magics.h"
46
47
48/*******************************************************************************
49* Structures and Typedefs *
50*******************************************************************************/
51/**
52 * Guarded memory allocation record.
53 */
54typedef struct RTTESTGUARDEDMEM
55{
56 /** Pointer to the next record. */
57 struct RTTESTGUARDEDMEM *pNext;
58 /** The address we return to the user. */
59 void *pvUser;
60 /** The base address of the allocation. */
61 void *pvAlloc;
62 /** The size of the allocation. */
63 size_t cbAlloc;
64 /** Guards. */
65 struct
66 {
67 /** The guard address. */
68 void *pv;
69 /** The guard size. */
70 size_t cb;
71 } aGuards[2];
72} RTTESTGUARDEDMEM;
73/** Pointer to an guarded memory allocation. */
74typedef RTTESTGUARDEDMEM *PRTTESTGUARDEDMEM;
75
76/**
77 * Test instance structure.
78 */
79typedef struct RTTESTINT
80{
81 /** Magic. */
82 uint32_t u32Magic;
83 /** The number of errors. */
84 volatile uint32_t cErrors;
85 /** The test name. */
86 const char *pszTest;
87 /** The length of the test name. */
88 unsigned cchTest;
89 /** The size of a guard. Multiple of PAGE_SIZE. */
90 uint32_t cbGuard;
91
92 /** Critical section seralizing access to the members following it. */
93 RTCRITSECT Lock;
94 /** The list of guarded memory allocations. */
95 PRTTESTGUARDEDMEM pGuardedMem;
96
97 /** Critical section seralizing output. */
98 RTCRITSECT OutputLock;
99 /** The output stream. */
100 PRTSTREAM pOutStrm;
101 /** Whether we're currently at a newline. */
102 bool fNewLine;
103
104} RTTESTINT;
105/** Pointer to a test instance. */
106typedef RTTESTINT *PRTTESTINT;
107
108
109/*******************************************************************************
110* Defined Constants And Macros *
111*******************************************************************************/
112/** Validate a test instance. */
113#define RTTEST_VALID_RETURN(pTest) \
114 do { \
115 AssertPtrReturn(pTest, VERR_INVALID_HANDLE); \
116 AssertReturn(pTest->u32Magic == RTTESTINT_MAGIC, VERR_INVALID_HANDLE); \
117 } while (0)
118
119/** Gets and validates a test instance.
120 * If the handle is nil, we will try retrive it from the test TLS entry.
121 */
122#define RTTEST_GET_VALID_RETURN(pTest) \
123 do { \
124 if (pTest == NIL_RTTEST) \
125 pTest = (PRTTESTINT)RTTlsGet(g_iTestTls); \
126 AssertPtrReturn(pTest, VERR_INVALID_HANDLE); \
127 AssertReturn(pTest->u32Magic == RTTESTINT_MAGIC, VERR_INVALID_MAGIC); \
128 } while (0)
129
130
131/** Gets and validates a test instance.
132 * If the handle is nil, we will try retrive it from the test TLS entry.
133 */
134#define RTTEST_GET_VALID_RETURN_RC(pTest, rc) \
135 do { \
136 if (pTest == NIL_RTTEST) \
137 pTest = (PRTTESTINT)RTTlsGet(g_iTestTls); \
138 AssertPtrReturn(pTest, (rc)); \
139 AssertReturn(pTest->u32Magic == RTTESTINT_MAGIC, (rc)); \
140 } while (0)
141
142
143/*******************************************************************************
144* Internal Functions *
145*******************************************************************************/
146static void rtTestGuardedFreeOne(PRTTESTGUARDEDMEM pMem);
147
148
149/*******************************************************************************
150* Global Variables *
151*******************************************************************************/
152/** For serializing TLS init. */
153static RTONCE g_TestInitOnce = RTONCE_INITIALIZER;
154/** Our TLS entry. */
155static RTTLS g_iTestTls = NIL_RTTLS;
156
157
158
159/**
160 * Init TLS index once.
161 *
162 * @returns IPRT status code.
163 * @param pvUser1 Ignored.
164 * @param pvUser2 Ignored.
165 */
166static DECLCALLBACK(int32_t) rtTestInitOnce(void *pvUser1, void *pvUser2)
167{
168 NOREF(pvUser1);
169 NOREF(pvUser2);
170 return RTTlsAllocEx(&g_iTestTls, NULL);
171}
172
173
174
175/**
176 * Creates a test instance.
177 *
178 * @returns IPRT status code.
179 * @param pszTest The test name.
180 * @param phTest Where to store the test instance handle.
181 */
182RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
183{
184 /*
185 * Global init.
186 */
187 int rc = RTOnce(&g_TestInitOnce, rtTestInitOnce, NULL, NULL);
188 if (RT_FAILURE(rc))
189 return rc;
190
191 /*
192 * Create the instance.
193 */
194 PRTTESTINT pTest = (PRTTESTINT)RTMemAllocZ(sizeof(*pTest));
195 if (!pTest)
196 return VERR_NO_MEMORY;
197 pTest->u32Magic = RTTESTINT_MAGIC;
198 pTest->cbGuard = PAGE_SIZE * 7;
199 pTest->pszTest = RTStrDup(pszTest);
200 pTest->cchTest = (unsigned)strlen(pszTest);
201 pTest->pOutStrm = g_pStdOut;
202 pTest->fNewLine = true;
203
204 rc = RTCritSectInit(&pTest->Lock);
205 if (RT_SUCCESS(rc))
206 {
207 rc = RTCritSectInit(&pTest->OutputLock);
208 if (RT_SUCCESS(rc))
209 {
210
211 /*
212 * Associate it with our TLS entry unless there is already
213 * an instance there.
214 */
215 if (!RTTlsGet(g_iTestTls))
216 rc = RTTlsSet(g_iTestTls, pTest);
217 if (RT_SUCCESS(rc))
218 {
219 *phTest = pTest;
220 return VINF_SUCCESS;
221 }
222
223 /* bail out. */
224 RTCritSectDelete(&pTest->OutputLock);
225 }
226 RTCritSectDelete(&pTest->Lock);
227 }
228 pTest->u32Magic = 0;
229 RTStrFree((char *)pTest->pszTest);
230 RTMemFree(pTest);
231 return rc;
232}
233
234
235/**
236 * Destroys a test instance previously created by RTTestCreate.
237 *
238 * @returns IPRT status code.
239 * @param hTest The test handle. NIL_RTTEST is ignored.
240 */
241RTR3DECL(int) RTTestDestroy(RTTEST hTest)
242{
243 /*
244 * Validate
245 */
246 if (hTest == NIL_RTTEST)
247 return VINF_SUCCESS;
248 RTTESTINT *pTest = hTest;
249 RTTEST_VALID_RETURN(pTest);
250
251 /*
252 * Clean up.
253 */
254 if ((RTTESTINT *)RTTlsGet(g_iTestTls) == pTest)
255 RTTlsSet(g_iTestTls, NULL);
256
257 ASMAtomicWriteU32(&pTest->u32Magic, ~RTTESTINT_MAGIC);
258 RTCritSectDelete(&pTest->Lock);
259 RTCritSectDelete(&pTest->OutputLock);
260
261 /* free guarded memory. */
262 PRTTESTGUARDEDMEM pMem = pTest->pGuardedMem;
263 pTest->pGuardedMem = NULL;
264 while (pMem)
265 {
266 PRTTESTGUARDEDMEM pFree = pMem;
267 pMem = pMem->pNext;
268 rtTestGuardedFreeOne(pFree);
269 }
270
271 RTStrFree((char *)pTest->pszTest);
272 pTest->pszTest = NULL;
273 RTMemFree(pTest);
274 return VINF_SUCCESS;
275}
276
277
278
279/**
280 * Allocate a block of guarded memory.
281 *
282 * @returns IPRT status code.
283 * @param hTest The test handle. If NIL_RTTEST we'll use the one
284 * associated with the calling thread.
285 * @param cb The amount of memory to allocate.
286 * @param cbAlign The alignment of the returned block.
287 * @param fHead Head or tail optimized guard.
288 * @param ppvUser Where to return the pointer to the block.
289 */
290RTR3DECL(int) RTTestGuardedAlloc(RTTEST hTest, size_t cb, uint32_t cbAlign, bool fHead, void **ppvUser)
291{
292 PRTTESTINT pTest = hTest;
293 RTTEST_GET_VALID_RETURN(pTest);
294 if (cbAlign == 0)
295 cbAlign = 1;
296 AssertReturn(cbAlign <= PAGE_SIZE, VERR_INVALID_PARAMETER);
297 AssertReturn(cbAlign == (UINT32_C(1) << (ASMBitFirstSetU32(cbAlign) - 1)), VERR_INVALID_PARAMETER);
298
299 /*
300 * Allocate the record and block and initialize them.
301 */
302 int rc = VERR_NO_MEMORY;
303 PRTTESTGUARDEDMEM pMem = (PRTTESTGUARDEDMEM)RTMemAlloc(sizeof(*pMem));
304 if (RT_LIKELY(pMem))
305 {
306 size_t const cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
307 pMem->aGuards[0].cb = pMem->aGuards[1].cb = pTest->cbGuard;
308 pMem->cbAlloc = pMem->aGuards[0].cb + pMem->aGuards[1].cb + cbAligned;
309 pMem->pvAlloc = RTMemPageAlloc(pMem->cbAlloc);
310 if (pMem->pvAlloc)
311 {
312 pMem->aGuards[0].pv = pMem->pvAlloc;
313 pMem->pvUser = (uint8_t *)pMem->pvAlloc + pMem->aGuards[0].cb;
314 pMem->aGuards[1].pv = (uint8_t *)pMem->pvUser + cbAligned;
315 if (!fHead)
316 {
317 size_t off = cb & PAGE_OFFSET_MASK;
318 if (off)
319 {
320 off = PAGE_SIZE - RT_ALIGN_Z(off, cbAlign);
321 pMem->pvUser = (uint8_t *)pMem->pvUser + off;
322 }
323 }
324
325 /*
326 * Set up the guards and link the record.
327 */
328 ASMMemFill32(pMem->aGuards[0].pv, pMem->aGuards[0].cb, 0xdeadbeef);
329 ASMMemFill32(pMem->aGuards[1].pv, pMem->aGuards[1].cb, 0xdeadbeef);
330 rc = RTMemProtect(pMem->aGuards[0].pv, pMem->aGuards[0].cb, RTMEM_PROT_NONE);
331 if (RT_SUCCESS(rc))
332 {
333 rc = RTMemProtect(pMem->aGuards[1].pv, pMem->aGuards[1].cb, RTMEM_PROT_NONE);
334 if (RT_SUCCESS(rc))
335 {
336 *ppvUser = pMem->pvUser;
337
338 RTCritSectEnter(&pTest->Lock);
339 pMem->pNext = pTest->pGuardedMem;
340 pTest->pGuardedMem = pMem;
341 RTCritSectLeave(&pTest->Lock);
342
343 return VINF_SUCCESS;
344 }
345
346 RTMemProtect(pMem->aGuards[0].pv, pMem->aGuards[0].cb, RTMEM_PROT_WRITE | RTMEM_PROT_READ);
347 }
348
349 RTMemPageFree(pMem->pvAlloc);
350 }
351 RTMemFree(pMem);
352 }
353 return rc;
354}
355
356
357/**
358 * Allocates a block of guarded memory where the guarded is immediately after
359 * the user memory.
360 *
361 * @returns Pointer to the allocated memory. NULL on failure.
362 * @param hTest The test handle. If NIL_RTTEST we'll use the one
363 * associated with the calling thread.
364 * @param cb The amount of memory to allocate.
365 */
366RTR3DECL(void *) RTTestGuardedAllocTail(RTTEST hTest, size_t cb)
367{
368 void *pvUser;
369 int rc = RTTestGuardedAlloc(hTest, cb, 1, false /*fHead*/, &pvUser);
370 if (RT_SUCCESS(rc))
371 return pvUser;
372 return NULL;
373}
374
375
376/**
377 * Allocates a block of guarded memory where the guarded is right in front of
378 * the user memory.
379 *
380 * @returns Pointer to the allocated memory. NULL on failure.
381 * @param hTest The test handle. If NIL_RTTEST we'll use the one
382 * associated with the calling thread.
383 * @param cb The amount of memory to allocate.
384 */
385RTR3DECL(void *) RTTestGuardedAllocHead(RTTEST hTest, size_t cb)
386{
387 void *pvUser;
388 int rc = RTTestGuardedAlloc(hTest, cb, 1, true /*fHead*/, &pvUser);
389 if (RT_SUCCESS(rc))
390 return pvUser;
391 return NULL;
392}
393
394
395/**
396 * Frees one block of guarded memory.
397 *
398 * The caller is responsible for unlinking it.
399 *
400 * @param pMem The memory record.
401 */
402static void rtTestGuardedFreeOne(PRTTESTGUARDEDMEM pMem)
403{
404 int rc;
405 rc = RTMemProtect(pMem->aGuards[0].pv, pMem->aGuards[0].cb, RTMEM_PROT_WRITE | RTMEM_PROT_READ); AssertRC(rc);
406 rc = RTMemProtect(pMem->aGuards[1].pv, pMem->aGuards[1].cb, RTMEM_PROT_WRITE | RTMEM_PROT_READ); AssertRC(rc);
407 RTMemPageFree(pMem->pvAlloc);
408 RTMemFree(pMem);
409}
410
411
412/**
413 * Frees a block of guarded memory.
414 *
415 * @returns IPRT status code.
416 * @param hTest The test handle. If NIL_RTTEST we'll use the one
417 * associated with the calling thread.
418 * @param pv The memory. NULL is ignored.
419 */
420RTR3DECL(int) RTTestGuardedFree(RTTEST hTest, void *pv)
421{
422 PRTTESTINT pTest = hTest;
423 RTTEST_GET_VALID_RETURN(pTest);
424 if (!pv)
425 return VINF_SUCCESS;
426
427 /*
428 * Find it.
429 */
430 int rc = VERR_INVALID_POINTER;
431 PRTTESTGUARDEDMEM pPrev = NULL;
432
433 RTCritSectEnter(&pTest->Lock);
434 for (PRTTESTGUARDEDMEM pMem = pTest->pGuardedMem; pMem; pMem = pMem->pNext)
435 {
436 if (pMem->pvUser == pv)
437 {
438 if (pPrev)
439 pPrev->pNext = pMem->pNext;
440 else
441 pTest->pGuardedMem = pMem->pNext;
442 rtTestGuardedFreeOne(pMem);
443 rc = VINF_SUCCESS;
444 break;
445 }
446 pPrev = pMem;
447 }
448 RTCritSectLeave(&pTest->Lock);
449
450 return VINF_SUCCESS;
451}
452
453
454/**
455 * Output callback.
456 *
457 * @returns number of bytes written.
458 * @param pvArg User argument.
459 * @param pachChars Pointer to an array of utf-8 characters.
460 * @param cbChars Number of bytes in the character array pointed to by pachChars.
461 */
462static DECLCALLBACK(size_t) rtTestPrintfOutput(void *pvArg, const char *pachChars, size_t cbChars)
463{
464 size_t cch = 0;
465 PRTTESTINT pTest = (PRTTESTINT)pvArg;
466 if (cbChars)
467 {
468 do
469 {
470 /* insert prefix if at a newline. */
471 if (pTest->fNewLine)
472 {
473 RTStrmWrite(pTest->pOutStrm, pTest->pszTest, pTest->cchTest);
474 RTStrmWrite(pTest->pOutStrm, ": ", 2);
475 cch += 2 + pTest->cchTest;
476 }
477
478 /* look for newline and write the stuff. */
479 const char *pchEnd = (const char *)memchr(pachChars, '\n', cbChars);
480 if (!pchEnd)
481 {
482 pTest->fNewLine = false;
483 RTStrmWrite(pTest->pOutStrm, pachChars, cbChars);
484 cch += cbChars;
485 break;
486 }
487
488 pTest->fNewLine = true;
489 size_t const cchPart = pchEnd - pachChars + 1;
490 RTStrmWrite(pTest->pOutStrm, pachChars, cchPart);
491 cch += cchPart;
492 pachChars += cchPart;
493 cbChars -= cchPart;
494 } while (cbChars);
495 }
496 else
497 RTStrmFlush(pTest->pOutStrm);
498 return cch;
499}
500
501
502/**
503 * Internal output worker.
504 *
505 * Caller takes the lock.
506 *
507 * @returns Number of chars printed.
508 * @param pTest The test instance.
509 * @param pszFormat The message.
510 * @param va The arguments.
511 */
512static int rtTestPrintfV(PRTTESTINT pTest, const char *pszFormat, va_list va)
513{
514 return (int)RTStrFormatV(rtTestPrintfOutput, pTest, NULL, NULL, pszFormat, va);
515}
516
517
518/**
519 * Internal output worker.
520 *
521 * Caller takes the lock.
522 *
523 * @returns Number of chars printed.
524 * @param pTest The test instance.
525 * @param pszFormat The message.
526 * @param ... The arguments.
527 */
528static int rtTestPrintf(PRTTESTINT pTest, const char *pszFormat, ...)
529{
530 va_list va;
531
532 va_start(va, pszFormat);
533 int cch = rtTestPrintfV(pTest, pszFormat, va);
534 va_end(va);
535
536 return cch;
537}
538
539
540/**
541 * Test vprintf making sure the output starts on a new line.
542 *
543 * @returns Number of chars printed.
544 * @param hTest The test handle. If NIL_RTTEST we'll use the one
545 * associated with the calling thread.
546 * @param pszFormat The message.
547 * @param va Arguments.
548 */
549RTR3DECL(int) RTTestPrintfNlV(RTTEST hTest, const char *pszFormat, va_list va)
550{
551 PRTTESTINT pTest = hTest;
552 RTTEST_GET_VALID_RETURN_RC(pTest, -1);
553
554 RTCritSectEnter(&pTest->OutputLock);
555
556 int cch = 0;
557 if (!pTest->fNewLine)
558 cch += rtTestPrintf(pTest, "\n");
559 cch += rtTestPrintfV(pTest, pszFormat, va);
560
561 RTCritSectLeave(&pTest->OutputLock);
562
563 return cch;
564}
565
566
567/**
568 * Test printf making sure the output starts on a new line.
569 *
570 * @returns Number of chars printed.
571 * @param hTest The test handle. If NIL_RTTEST we'll use the one
572 * associated with the calling thread.
573 * @param pszFormat The message.
574 * @param ... Arguments.
575 */
576RTR3DECL(int) RTTestPrintfNl(RTTEST hTest, const char *pszFormat, ...)
577{
578 va_list va;
579
580 va_start(va, pszFormat);
581 int cch = RTTestPrintfNlV(hTest, pszFormat, va);
582 va_end(va);
583
584 return cch;
585}
586
587
588/**
589 * Test vprintf, makes sure lines are prefixed and so forth.
590 *
591 * @returns Number of chars printed.
592 * @param hTest The test handle. If NIL_RTTEST we'll use the one
593 * associated with the calling thread.
594 * @param pszFormat The message.
595 * @param va Arguments.
596 */
597RTR3DECL(int) RTTestPrintfV(RTTEST hTest, const char *pszFormat, va_list va)
598{
599 PRTTESTINT pTest = hTest;
600 RTTEST_GET_VALID_RETURN_RC(pTest, -1);
601
602 RTCritSectEnter(&pTest->OutputLock);
603 int cch = rtTestPrintfV(pTest, pszFormat, va);
604 RTCritSectLeave(&pTest->OutputLock);
605
606 return cch;
607}
608
609
610/**
611 * Test printf, makes sure lines are prefixed and so forth.
612 *
613 * @returns Number of chars printed.
614 * @param hTest The test handle. If NIL_RTTEST we'll use the one
615 * associated with the calling thread.
616 * @param pszFormat The message.
617 * @param ... Arguments.
618 */
619RTR3DECL(int) RTTestPrintf(RTTEST hTest, const char *pszFormat, ...)
620{
621 va_list va;
622
623 va_start(va, pszFormat);
624 int cch = RTTestPrintfV(hTest, pszFormat, va);
625 va_end(va);
626
627 return cch;
628}
629
630
631/**
632 * Prints the test banner.
633 *
634 * @returns Number of chars printed.
635 * @param hTest The test handle. If NIL_RTTEST we'll use the one
636 * associated with the calling thread.
637 */
638RTR3DECL(int) RTTestBanner(RTTEST hTest)
639{
640 return RTTestPrintfNl(hTest, "TESTING...\n");
641}
642
643
644/**
645 * Summaries the test, destroys the test instance and return an exit code.
646 *
647 * @returns Test program exit code.
648 * @param hTest The test handle. If NIL_RTTEST we'll use the one
649 * associated with the calling thread.
650 */
651RTR3DECL(int) RTTestSummaryAndDestroy(RTTEST hTest)
652{
653 PRTTESTINT pTest = hTest;
654 RTTEST_GET_VALID_RETURN_RC(pTest, 2);
655
656 int rc;
657 if (!pTest->cErrors)
658 {
659 RTTestPrintfNl(hTest, "SUCCESS\n", pTest->cErrors);
660 rc = 0;
661 }
662 else
663 {
664 RTTestPrintfNl(hTest, "FAILURE - %u errors\n", pTest->cErrors);
665 rc = 1;
666 }
667
668 RTTestDestroy(pTest);
669 return rc;
670}
671
672
673/**
674 * Increments the error counter.
675 *
676 * @returns IPRT status code.
677 * @param hTest The test handle. If NIL_RTTEST we'll use the one
678 * associated with the calling thread.
679 */
680RTR3DECL(int) RTTestErrorInc(RTTEST hTest)
681{
682 PRTTESTINT pTest = hTest;
683 RTTEST_GET_VALID_RETURN(pTest);
684 ASMAtomicIncU32(&pTest->cErrors);
685 return VINF_SUCCESS;
686}
687
688
689/**
690 * Increments the error counter and prints a failure message.
691 *
692 * @returns IPRT status code.
693 * @param hTest The test handle. If NIL_RTTEST we'll use the one
694 * associated with the calling thread.
695 * @param pszFormat The message. No trailing newline.
696 * @param va The arguments.
697 */
698RTR3DECL(int) RTTestFailedV(RTTEST hTest, const char *pszFormat, va_list va)
699{
700 PRTTESTINT pTest = hTest;
701 RTTEST_GET_VALID_RETURN_RC(pTest, -1);
702
703 va_list va2;
704 va_copy(va2, va);
705
706 RTCritSectEnter(&pTest->OutputLock);
707 ASMAtomicIncU32(&pTest->cErrors);
708
709 int cch = rtTestPrintf(pTest, "FAILED - %N\n", pszFormat, &va2);
710
711 RTCritSectLeave(&pTest->OutputLock);
712
713 va_end(va2);
714
715 return cch;
716}
717
718
719/**
720 * Increments the error counter and prints a failure message.
721 *
722 * @returns IPRT status code.
723 * @param hTest The test handle. If NIL_RTTEST we'll use the one
724 * associated with the calling thread.
725 * @param pszFormat The message. No trailing newline.
726 * @param ... The arguments.
727 */
728RTR3DECL(int) RTTestFailed(RTTEST hTest, const char *pszFormat, ...)
729{
730 va_list va;
731
732 va_start(va, pszFormat);
733 int cch = RTTestFailedV(hTest, pszFormat, va);
734 va_end(va);
735
736 return cch;
737}
738
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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