diff options
Diffstat (limited to 'src/VBox/Runtime/r3/test.cpp')
-rw-r--r-- | src/VBox/Runtime/r3/test.cpp | 350 |
1 files changed, 240 insertions, 110 deletions
diff --git a/src/VBox/Runtime/r3/test.cpp b/src/VBox/Runtime/r3/test.cpp index 6c9abcc3..5688dc6c 100644 --- a/src/VBox/Runtime/r3/test.cpp +++ b/src/VBox/Runtime/r3/test.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -91,6 +91,8 @@ typedef struct RTTESTINT uint32_t cbGuard; /** The verbosity level. */ RTTESTLVL enmMaxLevel; + /** The creation flags. */ + uint32_t fFlags; /** Critical section serializing output. */ @@ -111,6 +113,8 @@ typedef struct RTTESTINT const char *pszSubTest; /** The length of the sub-test name. */ size_t cchSubTest; + /** Whether the current subtest should figure as 'SKIPPED'. */ + bool fSubTestSkipped; /** Whether we've reported the sub-test result or not. */ bool fSubTestReported; /** The start error count of the current subtest. */ @@ -123,6 +127,10 @@ typedef struct RTTESTINT /** Set if XML output is enabled. */ bool fXmlEnabled; + /** Set if we omit the top level test in the XML report. */ + bool fXmlOmitTopTest; + /** Set if we've reported the top test (for RTTEST_C_XML_DELAY_TOP_TEST). */ + bool fXmlTopTestDone; enum { kXmlPos_ValueStart, kXmlPos_Value, @@ -185,8 +193,6 @@ static void rtTestXmlElemV(PRTTESTINT pTest, const char *pszTag, const char *psz static void rtTestXmlElem(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...); static void rtTestXmlElemStartV(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, va_list va); static void rtTestXmlElemStart(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...); -static void rtTestXmlElemValueV(PRTTESTINT pTest, const char *pszFormat, va_list va); -static void rtTestXmlElemValue(PRTTESTINT pTest, const char *pszFormat, ...); static void rtTestXmlElemEnd(PRTTESTINT pTest, const char *pszTag); static void rtTestXmlEnd(PRTTESTINT pTest); @@ -205,31 +211,28 @@ static RTTLS g_iTestTls = NIL_RTTLS; * Init TLS index once. * * @returns IPRT status code. - * @param pvUser1 Ignored. - * @param pvUser2 Ignored. + * @param pvUser Ignored. */ -static DECLCALLBACK(int32_t) rtTestInitOnce(void *pvUser1, void *pvUser2) +static DECLCALLBACK(int32_t) rtTestInitOnce(void *pvUser) { - NOREF(pvUser1); - NOREF(pvUser2); + NOREF(pvUser); return RTTlsAllocEx(&g_iTestTls, NULL); } - -/** - * Creates a test instance. - * - * @returns IPRT status code. - * @param pszTest The test name. - * @param phTest Where to store the test instance handle. - */ -RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) +RTR3DECL(int) RTTestCreateEx(const char *pszTest, uint32_t fFlags, RTTESTLVL enmMaxLevel, + RTHCINTPTR iNativeTestPipe, const char *pszXmlFile, PRTTEST phTest) { + AssertReturn(!(fFlags & ~RTTEST_C_VALID_MASK), VERR_INVALID_PARAMETER); + AssertPtrNull(phTest); + AssertPtrNull(pszXmlFile); + /* RTTESTLVL_INVALID is valid! */ + AssertReturn(enmMaxLevel >= RTTESTLVL_INVALID && enmMaxLevel < RTTESTLVL_END, VERR_INVALID_PARAMETER); + /* * Global init. */ - int rc = RTOnce(&g_TestInitOnce, rtTestInitOnce, NULL, NULL); + int rc = RTOnce(&g_TestInitOnce, rtTestInitOnce, NULL); if (RT_FAILURE(rc)) return rc; @@ -243,7 +246,8 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) pTest->pszTest = RTStrDup(pszTest); pTest->cchTest = strlen(pszTest); pTest->cbGuard = PAGE_SIZE * 7; - pTest->enmMaxLevel = RTTESTLVL_SUB_TEST; + pTest->enmMaxLevel = enmMaxLevel == RTTESTLVL_INVALID ? RTTESTLVL_INFO : enmMaxLevel; + pTest->fFlags = fFlags; pTest->pOutStrm = g_pStdOut; pTest->fNewLine = true; @@ -252,12 +256,14 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) pTest->pszSubTest = NULL; pTest->cchSubTest = 0; + pTest->fSubTestSkipped = false; pTest->fSubTestReported = true; pTest->cSubTestAtErrors = 0; pTest->cSubTests = 0; pTest->cSubTestsFailed = 0; pTest->fXmlEnabled = false; + pTest->fXmlTopTestDone = false; pTest->eXmlState = RTTESTINT::kXmlPos_ElementEnd; pTest->hXmlPipe = NIL_RTPIPE; pTest->hXmlFile = NIL_RTFILE; @@ -273,82 +279,109 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) * Associate it with our TLS entry unless there is already * an instance there. */ - if (!RTTlsGet(g_iTestTls)) + if ( !(fFlags & RTTEST_C_NO_TLS) + && !RTTlsGet(g_iTestTls)) rc = RTTlsSet(g_iTestTls, pTest); if (RT_SUCCESS(rc)) { /* - * Pick up overrides from the environment. + * Output level override? */ char szEnvVal[RTPATH_MAX]; - rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_MAX_LEVEL", szEnvVal, sizeof(szEnvVal), NULL); - if (RT_SUCCESS(rc)) + if ((fFlags & RTTEST_C_USE_ENV) && enmMaxLevel == RTTESTLVL_INVALID) { - char *pszMaxLevel = RTStrStrip(szEnvVal); - if (!strcmp(pszMaxLevel, "all")) - pTest->enmMaxLevel = RTTESTLVL_DEBUG; - if (!strcmp(pszMaxLevel, "quiet")) - pTest->enmMaxLevel = RTTESTLVL_FAILURE; - else if (!strcmp(pszMaxLevel, "debug")) - pTest->enmMaxLevel = RTTESTLVL_DEBUG; - else if (!strcmp(pszMaxLevel, "info")) - pTest->enmMaxLevel = RTTESTLVL_INFO; - else if (!strcmp(pszMaxLevel, "sub_test")) - pTest->enmMaxLevel = RTTESTLVL_SUB_TEST; - else if (!strcmp(pszMaxLevel, "failure")) - pTest->enmMaxLevel = RTTESTLVL_FAILURE; + rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_MAX_LEVEL", szEnvVal, sizeof(szEnvVal), NULL); + if (RT_SUCCESS(rc)) + { + char *pszMaxLevel = RTStrStrip(szEnvVal); + if (!strcmp(pszMaxLevel, "all")) + pTest->enmMaxLevel = RTTESTLVL_DEBUG; + if (!strcmp(pszMaxLevel, "quiet")) + pTest->enmMaxLevel = RTTESTLVL_FAILURE; + else if (!strcmp(pszMaxLevel, "debug")) + pTest->enmMaxLevel = RTTESTLVL_DEBUG; + else if (!strcmp(pszMaxLevel, "info")) + pTest->enmMaxLevel = RTTESTLVL_INFO; + else if (!strcmp(pszMaxLevel, "sub_test")) + pTest->enmMaxLevel = RTTESTLVL_SUB_TEST; + else if (!strcmp(pszMaxLevel, "failure")) + pTest->enmMaxLevel = RTTESTLVL_FAILURE; + } + else if (rc != VERR_ENV_VAR_NOT_FOUND) + RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_MAX_LEVEL) -> %Rrc\n", pszTest, rc); } /* * Any test driver we are connected or should connect to? */ - rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_PIPE", szEnvVal, sizeof(szEnvVal), NULL); - if (RT_SUCCESS(rc)) + if ((fFlags & RTTEST_C_USE_ENV) && iNativeTestPipe == -1) { - RTHCINTPTR hNative = -1; + rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_PIPE", szEnvVal, sizeof(szEnvVal), NULL); + if (RT_SUCCESS(rc)) + { #if ARCH_BITS == 64 - rc = RTStrToInt64Full(szEnvVal, 0, &hNative); + rc = RTStrToInt64Full(szEnvVal, 0, &iNativeTestPipe); #else - rc = RTStrToInt32Full(szEnvVal, 0, &hNative); + rc = RTStrToInt32Full(szEnvVal, 0, &iNativeTestPipe); #endif - if (RT_SUCCESS(rc)) - { - rc = RTPipeFromNative(&pTest->hXmlPipe, hNative, RTPIPE_N_WRITE); - if (RT_SUCCESS(rc)) - pTest->fXmlEnabled = true; - else + if (RT_FAILURE(rc)) { - RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTPipeFromNative(,\"%s\",WRITE) -> %Rrc\n", pszTest, szEnvVal, rc); - pTest->hXmlPipe = NIL_RTPIPE; + RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTStrToInt32Full(\"%s\") -> %Rrc\n", + pszTest, szEnvVal, rc); + iNativeTestPipe = -1; } } + else if (rc != VERR_ENV_VAR_NOT_FOUND) + RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_PIPE) -> %Rrc\n", pszTest, rc); + } + if (iNativeTestPipe != -1) + { + rc = RTPipeFromNative(&pTest->hXmlPipe, iNativeTestPipe, RTPIPE_N_WRITE); + if (RT_SUCCESS(rc)) + pTest->fXmlEnabled = true; else - RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTStrToInt32Full(\"%s\") -> %Rrc\n", pszTest, szEnvVal, rc); + { + RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTPipeFromNative(,%p,WRITE) -> %Rrc\n", + pszTest, iNativeTestPipe, rc); + pTest->hXmlPipe = NIL_RTPIPE; + } } - else if (rc != VERR_ENV_VAR_NOT_FOUND) - RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_PIPE) -> %Rrc\n", pszTest, rc); /* * Any test file we should write the test report to? */ - rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_FILE", szEnvVal, sizeof(szEnvVal), NULL); - if (RT_SUCCESS(rc)) + if ((fFlags & RTTEST_C_USE_ENV) && pszXmlFile == NULL) { - rc = RTFileOpen(&pTest->hXmlFile, szEnvVal, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE); + rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_FILE", szEnvVal, sizeof(szEnvVal), NULL); + if (RT_SUCCESS(rc)) + pszXmlFile = szEnvVal; + else if (rc != VERR_ENV_VAR_NOT_FOUND) + RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_MAX_LEVEL) -> %Rrc\n", pszTest, rc); + } + if (pszXmlFile && *pszXmlFile) + { + rc = RTFileOpen(&pTest->hXmlFile, pszXmlFile, + RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_TRUNCATE); if (RT_SUCCESS(rc)) pTest->fXmlEnabled = true; else { - RTStrmPrintf(g_pStdErr, "%s: test file error: RTFileOpen(,\"%s\",) -> %Rrc\n", pszTest, szEnvVal, rc); + RTStrmPrintf(g_pStdErr, "%s: test file error: RTFileOpen(,\"%s\",) -> %Rrc\n", pszTest, pszXmlFile, rc); pTest->hXmlFile = NIL_RTFILE; } } else if (rc != VERR_ENV_VAR_NOT_FOUND) RTStrmPrintf(g_pStdErr, "%s: test file error: RTEnvGetEx(IPRT_TEST_FILE) -> %Rrc\n", pszTest, rc); + /* + * What do we report in the XML stream/file.? + */ + pTest->fXmlOmitTopTest = (fFlags & RTTEST_C_XML_OMIT_TOP_TEST) + || ( (fFlags & RTTEST_C_USE_ENV) + && RTEnvExistEx(RTENV_DEFAULT, "IPRT_TEST_OMIT_TOP_TEST")); /* - * Tell the test driver that we're up. + * Tell the test driver that we're up to. */ rtTestXmlStart(pTest, pszTest); @@ -368,6 +401,12 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) } +RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest) +{ + return RTTestCreateEx(pszTest, RTTEST_C_USE_ENV, RTTESTLVL_INVALID, -1 /*iNativeTestPipe*/, NULL /*pszXmlFile*/, phTest); +} + + RTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest) { int rc = RTR3InitExeNoArguments(0); @@ -376,6 +415,30 @@ RTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest) RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3InitExeNoArguments failed with rc=%Rrc\n", pszTest, rc); return RTEXITCODE_INIT; } + + rc = RTTestCreate(pszTest, phTest); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "%s: fatal error: RTTestCreate failed with rc=%Rrc\n", pszTest, rc); + return RTEXITCODE_INIT; + } + return RTEXITCODE_SUCCESS; +} + + +RTR3DECL(RTEXITCODE) RTTestInitExAndCreate(int cArgs, char ***papszArgs, uint32_t fRtInit, const char *pszTest, PRTTEST phTest) +{ + int rc; + if (cArgs <= 0 && papszArgs == NULL) + rc = RTR3InitExeNoArguments(fRtInit); + else + rc = RTR3InitExe(cArgs, papszArgs, fRtInit); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3InitExe(,,%#x) failed with rc=%Rrc\n", pszTest, fRtInit, rc); + return RTEXITCODE_INIT; + } + rc = RTTestCreate(pszTest, phTest); if (RT_FAILURE(rc)) { @@ -454,6 +517,34 @@ RTR3DECL(int) RTTestSetDefault(RTTEST hNewDefaultTest, PRTTEST phOldTest) } +RTR3DECL(int) RTTestChangeName(RTTEST hTest, const char *pszName) +{ + PRTTESTINT pTest = hTest; + RTTEST_GET_VALID_RETURN(pTest); + AssertPtrReturn(pszName, VERR_INVALID_POINTER); + AssertReturn(*pszName, VERR_INVALID_PARAMETER); + + size_t cchName = strlen(pszName); + AssertReturn(cchName < 128, VERR_INVALID_PARAMETER); + char *pszDupName = RTStrDup(pszName); + if (!pszDupName) + return VERR_NO_STR_MEMORY; + + RTCritSectEnter(&pTest->Lock); + RTCritSectEnter(&pTest->OutputLock); + + char *pszOldName = (char *)pTest->pszTest; + pTest->pszTest = pszDupName; + pTest->cchTest = cchName; + + RTCritSectLeave(&pTest->OutputLock); + RTCritSectLeave(&pTest->Lock); + + RTStrFree(pszOldName); + return VINF_SUCCESS; +} + + /** * Allocate a block of guarded memory. * @@ -683,7 +774,9 @@ static void rtTestXmlStart(PRTTESTINT pTest, const char *pszTest) { rtTestXmlOutput(pTest, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); pTest->eXmlState = RTTESTINT::kXmlPos_ElementEnd; - rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszTest); + pTest->fXmlTopTestDone = !(pTest->fFlags & RTTEST_C_XML_DELAY_TOP_TEST) || pTest->fXmlOmitTopTest; + if (pTest->fXmlTopTestDone && !pTest->fXmlOmitTopTest) + rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszTest); } } @@ -795,43 +888,6 @@ static void rtTestXmlElemStart(PRTTESTINT pTest, const char *pszTag, const char /** - * Writes an element value, or a part of one, taking care of all the escaping. - * - * The caller must own the instance lock. - * - * @param pTest The test instance. - * @param pszFormat The value format string. - * @param va The format arguments. - */ -static void rtTestXmlElemValueV(PRTTESTINT pTest, const char *pszFormat, va_list va) -{ - if (pTest->fXmlEnabled) - { - char *pszValue; - RTStrAPrintfV(&pszValue, pszFormat, va); - if (pszValue) - { - rtTestXmlOutput(pTest, "%RMes", pszValue); - RTStrFree(pszValue); - } - pTest->eXmlState = RTTESTINT::kXmlPos_Value; - } -} - - -/** - * Wrapper around rtTestXmlElemValueV. - */ -static void rtTestXmlElemValue(PRTTESTINT pTest, const char *pszFormat, ...) -{ - va_list va; - va_start(va, pszFormat); - rtTestXmlElemValueV(pTest, pszFormat, va); - va_end(va); -} - - -/** * Ends the current element. * * The caller must own the instance lock. @@ -879,7 +935,7 @@ static void rtTestXmlEnd(PRTTESTINT pTest) * final timestamp and some certainty that the XML is valid. */ size_t i = pTest->cXmlElements; - AssertReturnVoid(i > 0); + AssertReturnVoid(i > 0 || pTest->fXmlOmitTopTest || !pTest->fXmlTopTestDone); while (i-- > 1) { const char *pszTag = pTest->apszXmlElements[pTest->cXmlElements]; @@ -891,9 +947,13 @@ static void rtTestXmlEnd(PRTTESTINT pTest) rtTestXmlOutput(pTest, "</%s>\n", pszTag); pTest->eXmlState = RTTESTINT::kXmlPos_ElementEnd; } - rtTestXmlElem(pTest, "End", "SubTests=\"%u\" SubTestsFailed=\"%u\" errors=\"%u\"", - pTest->cSubTests, pTest->cSubTestsFailed, pTest->cErrors); - rtTestXmlOutput(pTest, "</Test>\n"); + + if (!pTest->fXmlOmitTopTest && pTest->fXmlTopTestDone) + { + rtTestXmlElem(pTest, "End", "SubTests=\"%u\" SubTestsFailed=\"%u\" errors=\"%u\"", + pTest->cSubTests, pTest->cSubTestsFailed, pTest->cErrors); + rtTestXmlOutput(pTest, "</Test>\n"); + } /* * Close the XML outputs. @@ -1130,15 +1190,24 @@ static int rtTestSubTestReport(PRTTESTINT pTest) uint32_t cErrors = ASMAtomicUoReadU32(&pTest->cErrors) - pTest->cSubTestAtErrors; if (!cErrors) { - rtTestXmlElem(pTest, "Passed", NULL); - rtTestXmlElemEnd(pTest, "SubTest"); - cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: PASSED\n", pTest->pszSubTest); + if (!pTest->fSubTestSkipped) + { + rtTestXmlElem(pTest, "Passed", NULL); + rtTestXmlElemEnd(pTest, "Test"); + cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: PASSED\n", pTest->pszSubTest); + } + else + { + rtTestXmlElem(pTest, "Skipped", NULL); + rtTestXmlElemEnd(pTest, "Test"); + cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: SKIPPED\n", pTest->pszSubTest); + } } else { pTest->cSubTestsFailed++; rtTestXmlElem(pTest, "Failed", "errors=\"%u\"", cErrors); - rtTestXmlElemEnd(pTest, "SubTest"); + rtTestXmlElemEnd(pTest, "Test"); cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: FAILED (%u errors)\n", pTest->pszSubTest, cErrors); } @@ -1267,13 +1336,20 @@ RTR3DECL(int) RTTestSub(RTTEST hTest, const char *pszSubTest) pTest->cSubTestAtErrors = ASMAtomicUoReadU32(&pTest->cErrors); pTest->pszSubTest = RTStrDup(pszSubTest); pTest->cchSubTest = strlen(pszSubTest); + pTest->fSubTestSkipped = false; pTest->fSubTestReported = false; int cch = 0; if (pTest->enmMaxLevel >= RTTESTLVL_DEBUG) cch = RTTestPrintfNl(hTest, RTTESTLVL_DEBUG, "debug: Starting sub-test '%s'\n", pszSubTest); - rtTestXmlElemStart(pTest, "SubTest", "name=%RMas", pszSubTest); + if (!pTest->fXmlTopTestDone) + { + pTest->fXmlTopTestDone = true; + rtTestXmlElemStart(pTest, "Test", "name=%RMas", pTest->pszTest); + } + + rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszSubTest); RTCritSectLeave(&pTest->Lock); @@ -1337,7 +1413,7 @@ RTR3DECL(int) RTTestSubV(RTTEST hTest, const char *pszSubTestFmt, va_list va) RTR3DECL(int) RTTestSubDone(RTTEST hTest) { PRTTESTINT pTest = hTest; - RTTEST_GET_VALID_RETURN_RC(pTest, -1); + RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE); RTCritSectEnter(&pTest->Lock); int cch = rtTestSubCleanup(pTest); @@ -1361,7 +1437,8 @@ RTR3DECL(int) RTTestSubDone(RTTEST hTest) RTR3DECL(int) RTTestPassedV(RTTEST hTest, const char *pszFormat, va_list va) { PRTTESTINT pTest = hTest; - RTTEST_GET_VALID_RETURN_RC(pTest, -1); + AssertPtr(pszFormat); + RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE); int cch = 0; if (pTest->enmMaxLevel >= RTTESTLVL_INFO) @@ -1404,6 +1481,44 @@ RTR3DECL(int) RTTestPassed(RTTEST hTest, const char *pszFormat, ...) } +RTR3DECL(int) RTTestSkippedV(RTTEST hTest, const char *pszFormat, va_list va) +{ + PRTTESTINT pTest = hTest; + AssertPtrNull(pszFormat); + RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE); + + pTest->fSubTestSkipped = true; + + int cch = 0; + if (pszFormat && *pszFormat && pTest->enmMaxLevel >= RTTESTLVL_INFO) + { + va_list va2; + va_copy(va2, va); + + RTCritSectEnter(&pTest->OutputLock); + cch += rtTestPrintf(pTest, "%N\n", pszFormat, &va2); + RTCritSectLeave(&pTest->OutputLock); + + va_end(va2); + } + + return cch; +} + + +RTR3DECL(int) RTTestSkipped(RTTEST hTest, const char *pszFormat, ...) +{ + va_list va; + + va_start(va, pszFormat); + int cch = RTTestSkippedV(hTest, pszFormat, va); + va_end(va); + + return cch; +} + + + /** * Gets the unit name. * @@ -1438,6 +1553,13 @@ static const char *rtTestUnitName(RTTESTUNIT enmUnit) case RTTESTUNIT_NS_PER_OCCURRENCE: return "ns/occurrences"; case RTTESTUNIT_NS_PER_PACKET: return "ns/packet"; case RTTESTUNIT_NS_PER_ROUND_TRIP: return "ns/roundtrips"; + case RTTESTUNIT_INSTRS: return "ins"; + case RTTESTUNIT_INSTRS_PER_SEC: return "ins/sec"; + case RTTESTUNIT_NONE: return ""; + case RTTESTUNIT_PP1K: return "pp1k"; + case RTTESTUNIT_PP10K: return "pp10k"; + case RTTESTUNIT_PPM: return "ppm"; + case RTTESTUNIT_PPB: return "ppb"; /* No default so gcc helps us keep this up to date. */ case RTTESTUNIT_INVALID: @@ -1457,9 +1579,7 @@ RTR3DECL(int) RTTestValue(RTTEST hTest, const char *pszName, uint64_t u64Value, const char *pszUnit = rtTestUnitName(enmUnit); RTCritSectEnter(&pTest->Lock); - rtTestXmlElemStart(pTest, "Value", "name=%RMas unit=%RMas", pszName, pszUnit); - rtTestXmlElemValue(pTest, "%llu", u64Value); - rtTestXmlElemEnd(pTest, "Value"); + rtTestXmlElem(pTest, "Value", "name=%RMas unit=%RMas value=\"%llu\"", pszName, pszUnit, u64Value); RTCritSectLeave(&pTest->Lock); RTCritSectEnter(&pTest->OutputLock); @@ -1510,6 +1630,7 @@ RTR3DECL(int) RTTestErrorInc(RTTEST hTest) } + /** * Get the current error count. * @@ -1526,6 +1647,15 @@ RTR3DECL(uint32_t) RTTestErrorCount(RTTEST hTest) } +RTR3DECL(uint32_t) RTTestSubErrorCount(RTTEST hTest) +{ + PRTTESTINT pTest = hTest; + RTTEST_GET_VALID_RETURN_RC(pTest, UINT32_MAX); + + return ASMAtomicReadU32(&pTest->cErrors) - pTest->cSubTestAtErrors; +} + + /** * Increments the error counter and prints a failure message. * @@ -1538,7 +1668,7 @@ RTR3DECL(uint32_t) RTTestErrorCount(RTTEST hTest) RTR3DECL(int) RTTestFailedV(RTTEST hTest, const char *pszFormat, va_list va) { PRTTESTINT pTest = hTest; - RTTEST_GET_VALID_RETURN_RC(pTest, -1); + RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE); RTTestErrorInc(pTest); |