test.cpp revision 9c2453b230526193ea4d5cf5a735dbff69a85a36
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * IPRT - Testcase Framework.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Copyright (C) 2009-2013 Oracle Corporation
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * available from http://www.virtualbox.org. This file is free software;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * General Public License (GPL) as published by the Free Software
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * The contents of this file may alternatively be used under the terms
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * of the Common Development and Distribution License Version 1.0
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * VirtualBox OSE distribution, in which case the provisions of the
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * CDDL are applicable instead of those of the GPL.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * You may elect to license modified versions of this file under the
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * terms and conditions of either the GPL or the CDDL or both.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/*******************************************************************************
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync* Header Files *
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync*******************************************************************************/
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/*******************************************************************************
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync* Structures and Typedefs *
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync*******************************************************************************/
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Guarded memory allocation record.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Pointer to the next record. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The address we return to the user. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The base address of the allocation. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The size of the allocation. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Guards. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The guard address. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The guard size. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/** Pointer to an guarded memory allocation. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Test instance structure.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsynctypedef struct RTTESTINT
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Magic. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The number of errors. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The test name. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync const char *pszTest;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The length of the test name. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The size of a guard. Multiple of PAGE_SIZE. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The verbosity level. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The creation flags. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Critical section serializing output. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The output stream. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Whether we're currently at a newline. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Critical section serializing access to the members following it. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The list of guarded memory allocations. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The current sub-test. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The length of the sub-test name. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Whether the current subtest should figure as 'SKIPPED'. */
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync /** Whether we've reported the sub-test result or not. */
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync /** The start error count of the current subtest. */
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync /** The number of sub tests. */
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync /** The number of sub tests that failed. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Set if XML output is enabled. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Set if we omit the top level test in the XML report. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Set if we've reported the top test (for RTTEST_C_XML_DELAY_TOP_TEST). */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** Test pipe for the XML output stream going to the server. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** File where the XML output stream might be directed. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** The number of XML elements on the stack. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /** XML element stack. */
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync/** Pointer to a test instance. */
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync/*******************************************************************************
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync* Defined Constants And Macros *
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync*******************************************************************************/
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync/** Validate a test instance. */
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync AssertReturn(pTest->u32Magic == RTTESTINT_MAGIC, VERR_INVALID_HANDLE); \
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync } while (0)
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync/** Gets and validates a test instance.
2e42e0850e182e37277fe28ba5b5d1c37018e783vboxsync * If the handle is nil, we will try retrieve it from the test TLS entry.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync AssertReturn(pTest->u32Magic == RTTESTINT_MAGIC, VERR_INVALID_MAGIC); \
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync } while (0)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/** Gets and validates a test instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * If the handle is nil, we will try retrieve it from the test TLS entry.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync AssertReturn(pTest->u32Magic == RTTESTINT_MAGIC, (rc)); \
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync } while (0)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/*******************************************************************************
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync* Internal Functions *
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync*******************************************************************************/
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestGuardedFreeOne(PRTTESTGUARDEDMEM pMem);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic int rtTestPrintf(PRTTESTINT pTest, const char *pszFormat, ...);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlStart(PRTTESTINT pTest, const char *pszTest);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemV(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, va_list va);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElem(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemStartV(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, va_list va);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemStart(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemEnd(PRTTESTINT pTest, const char *pszTag);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/*******************************************************************************
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync* Global Variables *
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync*******************************************************************************/
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/** For serializing TLS init. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync/** Our TLS entry. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Init TLS index once.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns IPRT status code.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pvUser Ignored.
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsyncstatic DECLCALLBACK(int32_t) rtTestInitOnce(void *pvUser)
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsyncRTR3DECL(int) RTTestCreateEx(const char *pszTest, uint32_t fFlags, RTTESTLVL enmMaxLevel,
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync RTHCINTPTR iNativeTestPipe, const char *pszXmlFile, PRTTEST phTest)
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync AssertReturn(!(fFlags & ~RTTEST_C_VALID_MASK), VERR_INVALID_PARAMETER);
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync /* RTTESTLVL_INVALID is valid! */
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync AssertReturn(enmMaxLevel >= RTTESTLVL_INVALID && enmMaxLevel < RTTESTLVL_END, VERR_INVALID_PARAMETER);
b011d23442f2b9e7208db889ff4b5ffe2c8effc8vboxsync * Global init.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync int rc = RTOnce(&g_TestInitOnce, rtTestInitOnce, NULL);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Create the instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync PRTTESTINT pTest = (PRTTESTINT)RTMemAllocZ(sizeof(*pTest));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync pTest->enmMaxLevel = enmMaxLevel == RTTESTLVL_INVALID ? RTTESTLVL_INFO : enmMaxLevel;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Associate it with our TLS entry unless there is already
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * an instance there.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Output level override?
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if ((fFlags & RTTEST_C_USE_ENV) && enmMaxLevel == RTTESTLVL_INVALID)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_MAX_LEVEL", szEnvVal, sizeof(szEnvVal), NULL);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_MAX_LEVEL) -> %Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Any test driver we are connected or should connect to?
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if ((fFlags & RTTEST_C_USE_ENV) && iNativeTestPipe == -1)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_PIPE", szEnvVal, sizeof(szEnvVal), NULL);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTStrToInt64Full(szEnvVal, 0, &iNativeTestPipe);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTStrToInt32Full(szEnvVal, 0, &iNativeTestPipe);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTStrToInt32Full(\"%s\") -> %Rrc\n",
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_PIPE) -> %Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTPipeFromNative(&pTest->hXmlPipe, iNativeTestPipe, RTPIPE_N_WRITE);
2805b95732a8d26015a397626b96049a6e6573e7vboxsync RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTPipeFromNative(,%p,WRITE) -> %Rrc\n",
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Any test file we should write the test report to?
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if ((fFlags & RTTEST_C_USE_ENV) && pszXmlFile == NULL)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_FILE", szEnvVal, sizeof(szEnvVal), NULL);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_MAX_LEVEL) -> %Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_TRUNCATE);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: test file error: RTFileOpen(,\"%s\",) -> %Rrc\n", pszTest, pszXmlFile, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: test file error: RTEnvGetEx(IPRT_TEST_FILE) -> %Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * What do we report in the XML stream/file.?
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync pTest->fXmlOmitTopTest = (fFlags & RTTEST_C_XML_OMIT_TOP_TEST)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync && RTEnvExistEx(RTENV_DEFAULT, "IPRT_TEST_OMIT_TOP_TEST"));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Tell the test driver that we're up to.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /* bail out. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync return RTTestCreateEx(pszTest, RTTEST_C_USE_ENV, RTTESTLVL_INVALID, -1 /*iNativeTestPipe*/, NULL /*pszXmlFile*/, phTest);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3InitExeNoArguments failed with rc=%Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: fatal error: RTTestCreate failed with rc=%Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(RTEXITCODE) RTTestInitExAndCreate(int cArgs, char ***papszArgs, uint32_t fRtInit, const char *pszTest, PRTTEST phTest)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3InitExe(,,%#x) failed with rc=%Rrc\n", pszTest, fRtInit, rc);
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync RTStrmPrintf(g_pStdErr, "%s: fatal error: RTTestCreate failed with rc=%Rrc\n", pszTest, rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Destroys a test instance previously created by RTTestCreate.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns IPRT status code.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param hTest The test handle. NIL_RTTEST is ignored.
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * Make sure we end with a new line and have finished up the XML.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Clean up.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync ASMAtomicWriteU32(&pTest->u32Magic, ~RTTESTINT_MAGIC);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /* free guarded memory. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Changes the default test instance for the calling thread.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns IPRT status code.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param hNewDefaultTest The new default test. NIL_RTTEST is fine.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param phOldTest Where to store the old test handle. Optional.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(int) RTTestSetDefault(RTTEST hNewDefaultTest, PRTTEST phOldTest)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(int) RTTestChangeName(RTTEST hTest, const char *pszName)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync AssertReturn(cchName < 128, VERR_INVALID_PARAMETER);
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * Allocate a block of guarded memory.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns IPRT status code.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param hTest The test handle. If NIL_RTTEST we'll use the one
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * associated with the calling thread.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param cb The amount of memory to allocate.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param cbAlign The alignment of the returned block.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param fHead Head or tail optimized guard.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param ppvUser Where to return the pointer to the block.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(int) RTTestGuardedAlloc(RTTEST hTest, size_t cb, uint32_t cbAlign, bool fHead, void **ppvUser)
2805b95732a8d26015a397626b96049a6e6573e7vboxsync AssertReturn(cbAlign <= PAGE_SIZE, VERR_INVALID_PARAMETER);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync AssertReturn(cbAlign == (UINT32_C(1) << (ASMBitFirstSetU32(cbAlign) - 1)), VERR_INVALID_PARAMETER);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Allocate the record and block and initialize them.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync PRTTESTGUARDEDMEM pMem = (PRTTESTGUARDEDMEM)RTMemAlloc(sizeof(*pMem));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync size_t const cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
f4859dbc9e6e61d81adba530beddf0c374ac9011vboxsync pMem->aGuards[0].cb = pMem->aGuards[1].cb = pTest->cbGuard;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync pMem->cbAlloc = pMem->aGuards[0].cb + pMem->aGuards[1].cb + cbAligned;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync pMem->pvUser = (uint8_t *)pMem->pvAlloc + pMem->aGuards[0].cb;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync pMem->aGuards[1].pv = (uint8_t *)pMem->pvUser + cbAligned;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Set up the guards and link the record.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync ASMMemFill32(pMem->aGuards[0].pv, pMem->aGuards[0].cb, 0xdeadbeef);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync ASMMemFill32(pMem->aGuards[1].pv, pMem->aGuards[1].cb, 0xdeadbeef);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTMemProtect(pMem->aGuards[0].pv, pMem->aGuards[0].cb, RTMEM_PROT_NONE);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTMemProtect(pMem->aGuards[1].pv, pMem->aGuards[1].cb, RTMEM_PROT_NONE);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTMemProtect(pMem->aGuards[0].pv, pMem->aGuards[0].cb, RTMEM_PROT_WRITE | RTMEM_PROT_READ);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Allocates a block of guarded memory where the guarded is immediately after
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * the user memory.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns Pointer to the allocated memory. NULL on failure.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param hTest The test handle. If NIL_RTTEST we'll use the one
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * associated with the calling thread.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param cb The amount of memory to allocate.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(void *) RTTestGuardedAllocTail(RTTEST hTest, size_t cb)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync int rc = RTTestGuardedAlloc(hTest, cb, 1, false /*fHead*/, &pvUser);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Allocates a block of guarded memory where the guarded is right in front of
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * the user memory.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns Pointer to the allocated memory. NULL on failure.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param hTest The test handle. If NIL_RTTEST we'll use the one
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * associated with the calling thread.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param cb The amount of memory to allocate.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(void *) RTTestGuardedAllocHead(RTTEST hTest, size_t cb)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync int rc = RTTestGuardedAlloc(hTest, cb, 1, true /*fHead*/, &pvUser);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Frees one block of guarded memory.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * The caller is responsible for unlinking it.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pMem The memory record.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestGuardedFreeOne(PRTTESTGUARDEDMEM pMem)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTMemProtect(pMem->aGuards[0].pv, pMem->aGuards[0].cb, RTMEM_PROT_WRITE | RTMEM_PROT_READ); AssertRC(rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rc = RTMemProtect(pMem->aGuards[1].pv, pMem->aGuards[1].cb, RTMEM_PROT_WRITE | RTMEM_PROT_READ); AssertRC(rc);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Frees a block of guarded memory.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @returns IPRT status code.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param hTest The test handle. If NIL_RTTEST we'll use the one
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * associated with the calling thread.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pv The memory. NULL is ignored.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncRTR3DECL(int) RTTestGuardedFree(RTTEST hTest, void *pv)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync for (PRTTESTGUARDEDMEM pMem = pTest->pGuardedMem; pMem; pMem = pMem->pNext)
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * Outputs the formatted XML.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pTest The test instance.
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * @param pszFormat The format string.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param va The format arguments.
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsyncstatic void rtTestXmlOutputV(PRTTESTINT pTest, const char *pszFormat, va_list va)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync ssize_t cchStr = RTStrAPrintfV(&pszStr, pszFormat, va);
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync RTPipeWriteBlocking(pTest->hXmlPipe, pszStr, cchStr, NULL);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTFileWrite(pTest->hXmlFile, pszStr, cchStr, NULL);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Outputs the formatted XML.
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * @param pTest The test instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszFormat The format string.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param ... The format arguments.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlOutput(PRTTESTINT pTest, const char *pszFormat, ...)
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * Starts the XML stream.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pTest The test instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszTest The test name.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlStart(PRTTESTINT pTest, const char *pszTest)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rtTestXmlOutput(pTest, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
f4859dbc9e6e61d81adba530beddf0c374ac9011vboxsync pTest->fXmlTopTestDone = !(pTest->fFlags & RTTEST_C_XML_DELAY_TOP_TEST) || pTest->fXmlOmitTopTest;
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if (pTest->fXmlTopTestDone && !pTest->fXmlOmitTopTest)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszTest);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Emit an XML element that doesn't have any value and instead ends immediately.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * The caller must own the instance lock.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pTest The test instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszTag The element tag.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszAttrFmt The element attributes as a format string. Use
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * NULL if none.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param va Format string arguments.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemV(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, va_list va)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTTimeToString(RTTimeExplode(&Time, RTTimeNow(&TimeSpec)), szTS, sizeof(szTS));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if (pTest->eXmlState != RTTESTINT::kXmlPos_ElementEnd)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rtTestXmlOutput(pTest, "%*s<%s timestamp=%RMas/>\n",
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rtTestXmlOutput(pTest, "%*s<%s timestamp=%RMas %N/>\n",
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync pTest->cXmlElements * 2, "", pszTag, szTS, pszAttrFmt, &va2);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Wrapper around rtTestXmlElemV.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElem(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Starts a new XML element.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * The caller must own the instance lock.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pTest The test instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszTag The element tag.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszAttrFmt The element attributes as a format string. Use
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * NULL if none.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param va Format string arguments.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemStartV(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, va_list va)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /* Push it onto the stack. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync AssertReturnVoid(i < RT_ELEMENTS(pTest->apszXmlElements));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync RTTimeToString(RTTimeExplode(&Time, RTTimeNow(&TimeSpec)), szTS, sizeof(szTS));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if (pTest->eXmlState != RTTESTINT::kXmlPos_ElementEnd)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rtTestXmlOutput(pTest, "%*s<%s timestamp=%RMas %N>",
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Wrapper around rtTestXmlElemStartV.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemStart(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...)
f2d4fe7c062d5d0501fadae94d1d3521bf31e4acvboxsync rtTestXmlElemStartV(pTest, pszTag, pszAttrFmt, va);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Ends the current element.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * The caller must own the instance lock.
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync * @param pTest The test instance.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pszTag The tag we're ending (chiefly for sanity
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * checking).
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsyncstatic void rtTestXmlElemEnd(PRTTESTINT pTest, const char *pszTag)
f2d4fe7c062d5d0501fadae94d1d3521bf31e4acvboxsync /* pop the element */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync AssertReturnVoid(!strcmp(pszTag, pTest->apszXmlElements[i]));
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync /* Do the closing. */
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync if (pTest->eXmlState == RTTESTINT::kXmlPos_ValueStart)
df3faec6dead5801ee07120bff7940a2c8ed6296vboxsync rtTestXmlOutput(pTest, "\n%*s</%s>\n", i * 2, "", pszTag);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync else if (pTest->eXmlState == RTTESTINT::kXmlPos_ElementEnd)
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync rtTestXmlOutput(pTest, "%*s</%s>\n", i * 2, "", pszTag);
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * Ends the XML stream, closing all open elements.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * The caller must own the instance lock.
e1fd337d575f2a4c053c6fe7a811e2fd1a31e874vboxsync * @param pTest The test instance.
if (cbChars)
if (!pchEnd)
} while (cbChars);
return cch;
return cch;
int cch = 0;
return cch;
return cch;
int cch = 0;
return cch;
return cch;
int cch = 0;
if (!cErrors)
return cch;
int cch = 0;
return cch;
return enmExitCode;
if (pszReasonFmt)
return enmExitCode;
return enmExitCode;
int cch = 0;
return cch;
return cch;
char *pszSubTest;
if (pszSubTest)
return cch;
return cch;
int cch = 0;
return cch;
return cch;
int cch = 0;
return cch;
return cch;
switch (enmUnit)
case RTTESTUNIT_INVALID:
case RTTESTUNIT_END:
return VINF_SUCCESS;
RTR3DECL(int) RTTestValueF(RTTEST hTest, uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, ...)
return rc;
RTR3DECL(int) RTTestValueV(RTTEST hTest, uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, va_list va)
char *pszName;
if (!pszName)
return VERR_NO_MEMORY;
return rc;
return VINF_SUCCESS;
int cch = 0;
return cch;
return cch;
return cch;