int main()
{
    /* How many integer test items should be created. */
    static const size_t s_cTestCount = 1000;

    RTTEST hTest;
    RTEXITCODE rcExit = RTTestInitAndCreate("tstIprtList", &hTest);
    if (rcExit)
        return rcExit;
    RTTestBanner(hTest);

    /*
     * Native types.
     */
    uint8_t au8TestInts[s_cTestCount];
    for (size_t i = 0; i < RT_ELEMENTS(au8TestInts); ++i)
        au8TestInts[i] = (uint8_t)RTRandU32Ex(1, UINT8_MAX);
    test1<RTCList,   uint8_t, uint8_t, uint8_t>("ST: Native type", au8TestInts, RT_ELEMENTS(au8TestInts));
    test1<RTCMTList, uint8_t, uint8_t, uint8_t>("MT: Native type", au8TestInts, RT_ELEMENTS(au8TestInts));

    uint16_t au16TestInts[s_cTestCount];
    for (size_t i = 0; i < RT_ELEMENTS(au16TestInts); ++i)
        au16TestInts[i] = (uint16_t)RTRandU32Ex(1, UINT16_MAX);
    test1<RTCList,   uint16_t, uint16_t, uint16_t>("ST: Native type", au16TestInts, RT_ELEMENTS(au16TestInts));
    test1<RTCMTList, uint16_t, uint16_t, uint16_t>("MT: Native type", au16TestInts, RT_ELEMENTS(au16TestInts));

    uint32_t au32TestInts[s_cTestCount];
    for (size_t i = 0; i < RT_ELEMENTS(au32TestInts); ++i)
        au32TestInts[i] = RTRandU32Ex(1, UINT32_MAX);
    test1<RTCList,   uint32_t, uint32_t, uint32_t>("ST: Native type", au32TestInts, RT_ELEMENTS(au32TestInts));
    test1<RTCMTList, uint32_t, uint32_t, uint32_t>("MT: Native type", au32TestInts, RT_ELEMENTS(au32TestInts));

    /*
     * Specialized type.
     */
    uint64_t au64TestInts[s_cTestCount];
    for (size_t i = 0; i < RT_ELEMENTS(au64TestInts); ++i)
        au64TestInts[i] = RTRandU64Ex(1, UINT64_MAX);
    test1<RTCList,   uint64_t, uint64_t, uint64_t>("ST: Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));
    test1<RTCMTList, uint64_t, uint64_t, uint64_t>("MT: Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));

    /*
     * Big size type (translate to internal pointer list).
     */
    test1<RTCList,   RTCString, RTCString *, const char *>("ST: Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));
    test1<RTCMTList, RTCString, RTCString *, const char *>("MT: Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));

    /*
     * Multi-threading test.
     */
    test2();

    /*
     * Summary.
     */
    return RTTestSummaryAndDestroy(hTest);
}
Beispiel #2
0
static void rtCreateTempFillTemplate(char *pszX, unsigned cXes)
{
    static char const s_sz[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    unsigned j = cXes;
    while (j-- > 0)
        pszX[j] = s_sz[RTRandU32Ex(0, RT_ELEMENTS(s_sz) - 2)];
}
Beispiel #3
0
static int testSessionDataReadTestMsg(RTTEST hTest, RTLOCALIPCSESSION hSession,
                                      void *pvBuffer, size_t cbBuffer, const char *pszMsg)
{
    AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
    AssertPtrReturn(pszMsg, VERR_INVALID_POINTER);

    void *pvBufCur = pvBuffer;
    size_t cbReadTotal = 0;
    for (;;)
    {
        size_t cbRead = RTRandU32Ex(1, sizeof(LOCALIPCTESTMSG) - cbReadTotal); /* Force a bit of fragmentation. */
        RTTEST_CHECK_BREAK(hTest, cbRead);
        RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionRead(hSession, pvBufCur,
                              cbBuffer,
                              &cbRead), VINF_SUCCESS);
        RTTEST_CHECK_BREAK(hTest, cbRead);
        pvBufCur     = (uint8_t *)pvBufCur + cbRead; /* Advance. */
        cbReadTotal += cbRead;
        RTTEST_CHECK_BREAK(hTest, cbReadTotal <= cbBuffer);
        if (cbReadTotal >= sizeof(LOCALIPCTESTMSG)) /* Got a complete test message? */
        {
            RTTEST_CHECK_BREAK(hTest, cbReadTotal == sizeof(LOCALIPCTESTMSG));
            PLOCALIPCTESTMSG pMsg = (PLOCALIPCTESTMSG)pvBuffer;
            RTTEST_CHECK_BREAK(hTest, pMsg != NULL);
            RTTEST_CHECK_BREAK(hTest, !RTStrCmp(pMsg->szOp, pszMsg));
            break;
        }
        /* Try receiving next part of the message in another round. */
    }

    return !RTTestErrorCount(hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */;
}
static int tstPDMACTestFileThread(PVM pVM, PPDMTHREAD pThread)
{
    PPDMACTESTFILE pTestFile = (PPDMACTESTFILE)pThread->pvUser;
    int iWriteChance = 100; /* Chance to get a write task in percent. */
    uint32_t cTasksStarted = 0;
    int rc = VINF_SUCCESS;

    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
        return VINF_SUCCESS;

    while (pTestFile->fRunning)
    {
        unsigned iTaskCurr = 0;


        /* Fill all tasks */
        while (   (pTestFile->cTasksActiveCurr < pTestFile->cTasksActiveMax)
               && (iTaskCurr < pTestFile->cTasksActiveMax))
        {
            PPDMACTESTFILETASK pTask = &pTestFile->paTasks[iTaskCurr];

            if (!pTask->fActive)
            {
                /* Read or write task? */
                bool fWrite = tstPDMACTestIsTrue(iWriteChance);

                ASMAtomicIncU32(&pTestFile->cTasksActiveCurr);

                if (fWrite)
                    rc = tstPDMACStressTestFileWrite(pTestFile, pTask);
                else
                    rc = tstPDMACStressTestFileRead(pTestFile, pTask);

                if (rc != VINF_AIO_TASK_PENDING)
                    tstPDMACStressTestFileTaskCompleted(pVM, pTask, pTestFile, rc);

                cTasksStarted++;
            }

            iTaskCurr++;
        }

        /*
         * Recalc write chance. The bigger the file the lower the chance to have a write.
         * The minimum chance is 33 percent.
         */
        iWriteChance = 100 - (int)(((float)100.0 / pTestFile->cbFileMax) * (float)pTestFile->cbFileCurr);
        iWriteChance = RT_MAX(33, iWriteChance);

        /* Wait a random amount of time. (1ms - 100ms) */
        RTThreadSleep(RTRandU32Ex(1, 100));
    }

    /* Wait for the rest to complete. */
    while (pTestFile->cTasksActiveCurr)
        RTThreadSleep(250);

    RTPrintf("Thread exiting: processed %u tasks\n", cTasksStarted);
    return rc;
}
static int tstPDMACStressTestFileRead(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
{
    int rc = VINF_SUCCESS;

    Assert(!pTestTask->fActive);

    pTestTask->fActive       = true;
    pTestTask->fWrite        = false;
    pTestTask->DataSeg.cbSeg = RTRandU32Ex(1, RT_MIN(pTestFile->cbFileCurr, TASK_TRANSFER_SIZE_MAX));

    AssertMsg(pTestFile->cbFileCurr >= pTestTask->DataSeg.cbSeg, ("Impossible\n"));
    pTestTask->off = RTRandU64Ex(0, pTestFile->cbFileCurr - pTestTask->DataSeg.cbSeg);

    /* Allocate data buffer. */
    pTestTask->DataSeg.pvSeg = RTMemAlloc(pTestTask->DataSeg.cbSeg);
    if (!pTestTask->DataSeg.pvSeg)
        return VERR_NO_MEMORY;

    /* Engage */
    rc = PDMR3AsyncCompletionEpRead(pTestFile->hEndpoint, pTestTask->off,
                                     &pTestTask->DataSeg, 1,
                                     pTestTask->DataSeg.cbSeg,
                                     pTestTask,
                                     &pTestTask->hTask);

    return rc;
}
/**
 * Thread for erasing items from a shared list.
 *
 * @param   hSelf       The thread handle.
 * @param   pvUser      The provided user data.
 */
DECLCALLBACK(int) mttest6(RTTHREAD hSelf, void *pvUser)
{
    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;

    /* Try to delete items from random places. */
    for (size_t i = 0; i < MTTESTITEMS; ++i)
    {
        /* Make sure there is at least one item in the list. */
        while (pTestList->isEmpty()) {};
        pTestList->removeAt(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1));
    }

    return VINF_SUCCESS;
}
Beispiel #7
0
static void doMemWipeThoroughly(RTTEST hTest)
{
    for (uint32_t p = 0; p < RTRandU32Ex(1, 64); p++)
    {
        size_t cbAlloc = RTRandS32Ex(1, _1M) * sizeof(uint8_t);

        RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Testing wipe #%.02RU32 (%u bytes) ...\n",
                     p + 1, cbAlloc);

        void *pvBuf = RTMemAlloc(cbAlloc);
        if (!pvBuf)
        {
            RTTestIFailed("No memory for first buffer (%z bytes)\n",
                          cbAlloc);
            continue;
        }
        RTRandBytes(pvBuf, cbAlloc);

        void *pvWipe = RTMemDup(pvBuf, cbAlloc);
        if (!pvWipe)
        {
            RTMemFree(pvBuf);

            RTTestIFailed("No memory for second buffer (%z bytes)\n",
                          cbAlloc);
            continue;
        }
        size_t cbWipeRand = RTRandU32Ex(1, cbAlloc);
        RTMemWipeThoroughly(pvWipe, RT_MIN(cbAlloc, cbWipeRand), p /* Passes */);
        if (!memcmp(pvWipe, pvBuf, cbAlloc))
            RTTestIFailed("Memory blocks must differ (%z bytes, 0x%p vs. 0x%p)!\n",
                          cbAlloc, pvWipe, pvBuf);

        RTMemFree(pvWipe);
        RTMemFree(pvBuf);
    }
}
/**
 * Thread for replacing items in a shared list.
 *
 * @param   hSelf       The thread handle.
 * @param   pvUser      The provided user data.
 */
static DECLCALLBACK(int) MtTest5ThreadProc(RTTHREAD hSelf, void *pvUser)
{
    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;

    /* Try to replace C items from random places. */
    for (size_t i = 0; i < MTTESTITEMS; ++i)
    {
        /* Make sure there is at least one item in the list. */
        while (pTestList->isEmpty())
            RTThreadYield();
        pTestList->replace(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1), 0xFF00FF00);
    }

    return VINF_SUCCESS;
}
Beispiel #9
0
int main()
{
    RTR3InitExeNoArguments(0);
    RTPrintf("tstRand: TESTING...\n");

    /*
     * Do some smoke tests first?
     */
    /** @todo RTRand smoke testing. */

#if 1
    /*
     * Test distribution.
     */
#if 1
    /* unsigned 32-bit */
    static const struct
    {
        uint32_t u32First;
        uint32_t u32Last;
    } s_aU32Tests[] =
    {
        { 0, UINT32_MAX },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 4 },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 8 },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 16 },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 64 },
        { 0, UINT32_MAX / 2 },
        { UINT32_MAX / 4, UINT32_MAX / 4 * 3 },
        { 0, TST_RAND_SAMPLE_RANGES - 1 },
        { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 },
    };
    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU32Tests); iTest++)
    {
        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0};
        uint32_t const uFirst = s_aU32Tests[iTest].u32First;
        uint32_t const uLast  = s_aU32Tests[iTest].u32Last;
        uint32_t const uRange = uLast - uFirst; Assert(uLast >= uFirst);
        uint32_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1;
        RTPrintf("tstRand: TESTING RTRandU32Ex(%#RX32, %#RX32) distribution... [div=%#RX32 range=%#RX32]\n", uFirst, uLast, uDivisor, uRange);
        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
        {
            uint32_t uRand = RTRandU32Ex(uFirst, uLast);
            CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX32 %#RX32\n", uRand, uFirst));
            CHECK_EXPR_MSG(uRand <= uLast,  ("%#RX32 %#RX32\n", uRand, uLast));
            uint32_t off = uRand - uFirst;
            acHits[off / uDivisor]++;
        }
        tstRandCheckDist(acHits, iTest);
    }
#endif

#if 1
    /* unsigned 64-bit */
    static const struct
    {
        uint64_t u64First;
        uint64_t u64Last;
    } s_aU64Tests[] =
    {
        { 0, UINT64_MAX },
        { 0, UINT64_MAX / 2 + UINT64_MAX / 4 },
        { 0, UINT64_MAX / 2 + UINT64_MAX / 8 },
        { 0, UINT64_MAX / 2 + UINT64_MAX / 16 },
        { 0, UINT64_MAX / 2 + UINT64_MAX / 64 },
        { 0, UINT64_MAX / 2 },
        { UINT64_MAX / 4, UINT64_MAX / 4 * 3 },
        { 0, UINT32_MAX },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 4 },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 8 },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 16 },
        { 0, UINT32_MAX / 2 + UINT32_MAX / 64 },
        { 0, UINT32_MAX / 2 },
        { UINT32_MAX / 4, UINT32_MAX / 4 * 3 },
        { 0, TST_RAND_SAMPLE_RANGES - 1 },
        { 1234, 1234 + TST_RAND_SAMPLE_RANGES - 1 },
    };
    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aU64Tests); iTest++)
    {
        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0};
        uint64_t const uFirst = s_aU64Tests[iTest].u64First;
        uint64_t const uLast  = s_aU64Tests[iTest].u64Last;
        uint64_t const uRange = uLast - uFirst;  Assert(uLast >= uFirst);
        uint64_t const uDivisor = uRange / TST_RAND_SAMPLE_RANGES + 1;
        RTPrintf("tstRand: TESTING RTRandU64Ex(%#RX64, %#RX64) distribution... [div=%#RX64 range=%#RX64]\n", uFirst, uLast, uDivisor, uRange);
        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
        {
            uint64_t uRand = RTRandU64Ex(uFirst, uLast);
            CHECK_EXPR_MSG(uRand >= uFirst, ("%#RX64 %#RX64\n", uRand, uFirst));
            CHECK_EXPR_MSG(uRand <= uLast,  ("%#RX64 %#RX64\n", uRand, uLast));
            uint64_t off = uRand - uFirst;
            acHits[off / uDivisor]++;
        }
        tstRandCheckDist(acHits, iTest);
    }
#endif

#if 1
    /* signed 32-bit */
    static const struct
    {
        int32_t i32First;
        int32_t i32Last;
    } s_aS32Tests[] =
    {
        { -429496729, 429496729 },
        { INT32_MIN, INT32_MAX },
        { INT32_MIN, INT32_MAX / 2 },
        { -0x20000000, INT32_MAX },
        { -0x10000000, INT32_MAX },
        { -0x08000000, INT32_MAX },
        { -0x00800000, INT32_MAX },
        { -0x00080000, INT32_MAX },
        { -0x00008000, INT32_MAX },
        { -0x00000800, INT32_MAX },
        { 2, INT32_MAX / 2 },
        { 4000000, INT32_MAX / 2 },
        { -4000000, INT32_MAX / 2 },
        { INT32_MIN / 2, INT32_MAX / 2 },
        { INT32_MIN / 3, INT32_MAX / 2 },
        { INT32_MIN / 3, INT32_MAX / 3 },
        { INT32_MIN / 3, INT32_MAX / 4 },
        { INT32_MIN / 4, INT32_MAX / 4 },
        { INT32_MIN / 5, INT32_MAX / 5 },
        { INT32_MIN / 6, INT32_MAX / 6 },
        { INT32_MIN / 7, INT32_MAX / 6 },
        { INT32_MIN / 7, INT32_MAX / 7 },
        { INT32_MIN / 7, INT32_MAX / 8 },
        { INT32_MIN / 8, INT32_MAX / 8 },
        { INT32_MIN / 9, INT32_MAX / 9 },
        { INT32_MIN / 9, INT32_MAX / 12 },
        { INT32_MIN / 12, INT32_MAX / 12 },
        { 0, TST_RAND_SAMPLE_RANGES - 1 },
        { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 },
    };
    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS32Tests); iTest++)
    {
        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0};
        int32_t const  iFirst = s_aS32Tests[iTest].i32First;
        int32_t const  iLast  = s_aS32Tests[iTest].i32Last;
        uint32_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest));
        uint32_t const uDivisor = (uRange ? uRange : UINT32_MAX) / TST_RAND_SAMPLE_RANGES + 1;
        RTPrintf("tstRand: TESTING RTRandS32Ex(%#RI32, %#RI32) distribution... [div=%#RX32 range=%#RX32]\n", iFirst, iLast, uDivisor, uRange);
        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
        {
            int32_t iRand = RTRandS32Ex(iFirst, iLast);
            CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI32 %#RI32\n", iRand, iFirst));
            CHECK_EXPR_MSG(iRand <= iLast,  ("%#RI32 %#RI32\n", iRand, iLast));
            uint32_t off = iRand - iFirst;
            acHits[off / uDivisor]++;
        }
        tstRandCheckDist(acHits, iTest);
    }
#endif

#if 1
    /* signed 64-bit */
    static const struct
    {
        int64_t i64First;
        int64_t i64Last;
    } s_aS64Tests[] =
    {
        { INT64_MIN, INT64_MAX },
        { INT64_MIN, INT64_MAX / 2 },
        { INT64_MIN / 2, INT64_MAX / 2 },
        { INT64_MIN / 2 + INT64_MIN / 4, INT64_MAX / 2 },
        { INT64_MIN / 2 + INT64_MIN / 8, INT64_MAX / 2 },
        { INT64_MIN / 2 + INT64_MIN / 16, INT64_MAX / 2 },
        { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 },
        { INT64_MIN / 2 + INT64_MIN / 64, INT64_MAX / 2 + INT64_MAX / 64 },
        { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 64 },
        { INT64_MIN / 2, INT64_MAX / 2 + INT64_MAX / 8 },
        { INT64_MIN / 2, INT64_MAX / 2 - INT64_MAX / 8 },
        { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 4 },
        { INT64_MIN / 2 - INT64_MIN / 4, INT64_MAX / 2 - INT64_MAX / 8 },
        { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 - INT64_MAX / 8 },
        { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 8 },
        { INT64_MIN / 2 - INT64_MIN / 16, INT64_MAX / 2 - INT64_MAX / 16 },
        { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 16 },
        { INT64_MIN / 2 - INT64_MIN / 32, INT64_MAX / 2 - INT64_MAX / 32 },
        { INT64_MIN / 2 - INT64_MIN / 64, INT64_MAX / 2 - INT64_MAX / 64 },
        { INT64_MIN / 2 - INT64_MIN / 8, INT64_MAX / 2 },
        { INT64_MIN / 4, INT64_MAX / 4 },
        { INT64_MIN / 5, INT64_MAX / 5 },
        { INT64_MIN / 6, INT64_MAX / 6 },
        { INT64_MIN / 7, INT64_MAX / 7 },
        { INT64_MIN / 8, INT64_MAX / 8 },
        { INT32_MIN, INT32_MAX },
        { INT32_MIN, INT32_MAX / 2 },
        { -0x20000000, INT32_MAX },
        { -0x10000000, INT32_MAX },
        { -0x7f000000, INT32_MAX },
        { -0x08000000, INT32_MAX },
        { -0x00800000, INT32_MAX },
        { -0x00080000, INT32_MAX },
        { -0x00008000, INT32_MAX },
        { 2, INT32_MAX / 2 },
        { 4000000, INT32_MAX / 2 },
        { -4000000, INT32_MAX / 2 },
        { INT32_MIN / 2, INT32_MAX / 2 },
        { 0, TST_RAND_SAMPLE_RANGES - 1 },
        { -TST_RAND_SAMPLE_RANGES / 2, TST_RAND_SAMPLE_RANGES / 2 - 1 }
    };
    for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aS64Tests); iTest++)
    {
        uint32_t       acHits[TST_RAND_SAMPLE_RANGES] = {0};
        int64_t const  iFirst = s_aS64Tests[iTest].i64First;
        int64_t const  iLast  = s_aS64Tests[iTest].i64Last;
        uint64_t const uRange = iLast - iFirst; AssertMsg(iLast >= iFirst, ("%d\n", iTest));
        uint64_t const uDivisor = (uRange ? uRange : UINT64_MAX) / TST_RAND_SAMPLE_RANGES + 1;
        RTPrintf("tstRand: TESTING RTRandS64Ex(%#RI64, %#RI64) distribution... [div=%#RX64 range=%#016RX64]\n", iFirst, iLast, uDivisor, uRange);
        for (unsigned iSample = 0; iSample < TST_RAND_SAMPLE_RANGES * 10240; iSample++)
        {
            int64_t iRand = RTRandS64Ex(iFirst, iLast);
            CHECK_EXPR_MSG(iRand >= iFirst, ("%#RI64 %#RI64\n", iRand, iFirst));
            CHECK_EXPR_MSG(iRand <= iLast,  ("%#RI64 %#RI64\n", iRand, iLast));
            uint64_t off = iRand - iFirst;
            acHits[off / uDivisor]++;
        }
        tstRandCheckDist(acHits, iTest);
    }
#endif
#endif /* Testing RTRand */

#if 1
    /*
     * Test the various random generators.
     */
    RTPrintf("tstRand: TESTING RTRandAdvCreateParkerMiller\n");
    RTRAND hRand;
    int rc = RTRandAdvCreateParkMiller(&hRand);
    CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc));
    if (RT_SUCCESS(rc))
        if (tstRandAdv(hRand))
            return 1;

#endif /* Testing RTRandAdv */

    /*
     * Summary.
     */
    if (!g_cErrors)
        RTPrintf("tstRand: SUCCESS\n");
    else
        RTPrintf("tstRand: FAILED - %d errors\n", g_cErrors);
    return !!g_cErrors;
}
RTDECL(int) RTDirCreateTemp(char *pszTemplate)
{
    /*
     * Validate input and count X'es.
     *
     * The X'es may be trailing, or they may be a cluster of 3 or more inside
     * the file name.
     */
    AssertPtr(pszTemplate);
    unsigned    cXes = 0;
    char       *pszX = strchr(pszTemplate, '\0');
    if (   pszX != pszTemplate
        && pszX[-1] != 'X')
    {
        /* look inside the file name. */
        char *pszFilename = RTPathFilename(pszTemplate);
        if (   pszFilename
            && (size_t)(pszX - pszFilename) > 3)
        {
            char *pszXEnd = pszX - 1;
            pszFilename += 3;
            do
            {
                if (    pszXEnd[-1] == 'X'
                    &&  pszXEnd[-2] == 'X'
                    &&  pszXEnd[-3] == 'X')
                {
                    pszX = pszXEnd - 3;
                    cXes = 3;
                    break;
                }
            } while (pszXEnd-- != pszFilename);
        }
    }

    /* count them */
    while (   pszX != pszTemplate
           && pszX[-1] == 'X')
    {
        pszX--;
        cXes++;
    }

    /* fail if none found. */
    if (!cXes)
    {
        AssertFailed();
        *pszTemplate = '\0';
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Try ten thousand times.
     */
    int i = 10000;
    while (i-- > 0)
    {
        static char const s_sz[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        unsigned j = cXes;
        while (j-- > 0)
            pszX[j] = s_sz[RTRandU32Ex(0, RT_ELEMENTS(s_sz) - 2)];
        int rc = RTDirCreate(pszTemplate, 0700);
        if (RT_SUCCESS(rc))
            return rc;
        if (rc != VERR_ALREADY_EXISTS)
        {
            *pszTemplate = '\0';
            return rc;
        }
    }

    /* we've given up. */
    *pszTemplate = '\0';
    return VERR_ALREADY_EXISTS;
}
/**
 * Sets up a test file creating the I/O thread.
 *
 * @returns VBox status code.
 * @param   pVM          Pointer to the shared VM instance structure.
 * @param   pTestFile    Pointer to the uninitialized test file structure.
 * @param   iTestId      Unique test id.
 */
static int tstPDMACStressTestFileOpen(PVM pVM, PPDMACTESTFILE pTestFile, unsigned iTestId)
{
    int rc = VERR_NO_MEMORY;

    /* Size is a multiple of 512 */
    pTestFile->cbFileMax     = RTRandU64Ex(FILE_SIZE_MIN, FILE_SIZE_MAX) & ~(511UL);
    pTestFile->cbFileCurr    = 0;
    pTestFile->cbFileSegment = RTRandU32Ex(SEGMENT_SIZE_MIN, RT_MIN(pTestFile->cbFileMax, SEGMENT_SIZE_MAX)) & ~((size_t)511);

    Assert(pTestFile->cbFileMax >= pTestFile->cbFileSegment);

    /* Set up the segments array. */
    pTestFile->cSegments  = pTestFile->cbFileMax / pTestFile->cbFileSegment;
    pTestFile->cSegments += ((pTestFile->cbFileMax % pTestFile->cbFileSegment) > 0) ? 1 : 0;

    pTestFile->paSegs = (PPDMACTESTFILESEG)RTMemAllocZ(pTestFile->cSegments * sizeof(PDMACTESTFILESEG));
    if (pTestFile->paSegs)
    {
        /* Init the segments */
        for (unsigned i = 0; i < pTestFile->cSegments; i++)
        {
            PPDMACTESTFILESEG pSeg = &pTestFile->paSegs[i];

            pSeg->off       = (RTFOFF)i * pTestFile->cbFileSegment;
            pSeg->cbSegment = pTestFile->cbFileSegment;

            /* Let the buffer point to a random position in the test pattern. */
            uint32_t offTestPattern = RTRandU64Ex(0, g_cbTestPattern - pSeg->cbSegment);

            pSeg->pbData = g_pbTestPattern + offTestPattern;
        }

        /* Init task array. */
        pTestFile->cTasksActiveMax = RTRandU32Ex(1, TASK_ACTIVE_MAX);
        pTestFile->paTasks         = (PPDMACTESTFILETASK)RTMemAllocZ(pTestFile->cTasksActiveMax * sizeof(PDMACTESTFILETASK));
        if (pTestFile->paTasks)
        {
            /* Create the template */
            char szDesc[256];

            RTStrPrintf(szDesc, sizeof(szDesc), "Template-%d", iTestId);
            rc = PDMR3AsyncCompletionTemplateCreateInternal(pVM, &pTestFile->pTemplate, tstPDMACStressTestFileTaskCompleted, pTestFile, szDesc);
            if (RT_SUCCESS(rc))
            {
                /* Open the endpoint now. Because async completion endpoints cannot create files we have to do it before. */
                char szFile[RTPATH_MAX];

                RTStrPrintf(szFile, sizeof(szFile), "tstPDMAsyncCompletionStress-%d.tmp", iTestId);

                RTFILE FileTmp;
                rc = RTFileOpen(&FileTmp, szFile, RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_NONE);
                if (RT_SUCCESS(rc))
                {
                    RTFileClose(FileTmp);

                    rc = PDMR3AsyncCompletionEpCreateForFile(&pTestFile->hEndpoint, szFile, 0, pTestFile->pTemplate);
                    if (RT_SUCCESS(rc))
                    {
                        char szThreadDesc[256];

                        pTestFile->fRunning = true;

                        /* Create the thread creating the I/O for the given file. */
                        RTStrPrintf(szThreadDesc, sizeof(szThreadDesc), "PDMACThread-%d", iTestId);
                        rc = PDMR3ThreadCreate(pVM, &pTestFile->hThread, pTestFile, tstPDMACTestFileThread,
                                               NULL, 0, RTTHREADTYPE_IO, szThreadDesc);
                        if (RT_SUCCESS(rc))
                        {
                            rc = PDMR3ThreadResume(pTestFile->hThread);
                            AssertRC(rc);

                            RTPrintf(TESTCASE ": Created test file %s cbFileMax=%llu cbFileSegment=%u cSegments=%u cTasksActiveMax=%u\n",
                                     szFile, pTestFile->cbFileMax, pTestFile->cbFileSegment, pTestFile->cSegments, pTestFile->cTasksActiveMax);
                            return VINF_SUCCESS;
                        }

                        PDMR3AsyncCompletionEpClose(pTestFile->hEndpoint);
                    }

                    RTFileDelete(szFile);
                }

                PDMR3AsyncCompletionTemplateDestroy(pTestFile->pTemplate);
            }

            RTMemFree(pTestFile->paTasks);
        }
        else
            rc = VERR_NO_MEMORY;

        RTMemFree(pTestFile->paSegs);
    }
    else
        rc = VERR_NO_MEMORY;

    RTPrintf(TESTCASE ": Opening test file with id %d failed rc=%Rrc\n", iTestId, rc);

    return rc;
}
/**
 * Returns true with the given chance in percent.
 *
 * @returns true or false
 * @param   iPercentage   The percentage of the chance to return true.
 */
static bool tstPDMACTestIsTrue(int iPercentage)
{
    int uRnd = RTRandU32Ex(0, 100);

    return (uRnd <= iPercentage); /* This should be enough for our purpose */
}
static int tstPDMACStressTestFileWrite(PPDMACTESTFILE pTestFile, PPDMACTESTFILETASK pTestTask)
{
    int rc = VINF_SUCCESS;

    Assert(!pTestTask->fActive);

    pTestTask->fActive       = true;
    pTestTask->fWrite        = true;
    pTestTask->DataSeg.cbSeg = RTRandU32Ex(512, TASK_TRANSFER_SIZE_MAX) & ~511;

    uint64_t offMax;

    /* Did we reached the maximum file size */
    if (pTestFile->cbFileCurr < pTestFile->cbFileMax)
    {
        offMax =   (pTestFile->cbFileMax - pTestFile->cbFileCurr) < pTestTask->DataSeg.cbSeg
                 ? pTestFile->cbFileMax - pTestTask->DataSeg.cbSeg
                 : pTestFile->cbFileCurr;
    }
    else
        offMax = pTestFile->cbFileMax - pTestTask->DataSeg.cbSeg;

    uint64_t offMin;

    /*
     * If we reached the maximum file size write in the whole file
     * otherwise we will enforce the range for random offsets to let it grow
     * more quickly.
     */
    if (pTestFile->cbFileCurr == pTestFile->cbFileMax)
        offMin = 0;
    else
        offMin = RT_MIN(pTestFile->cbFileCurr, offMax);


    pTestTask->off = RTRandU64Ex(offMin, offMax) & ~511;

    /* Set new file size of required */
    if ((uint64_t)pTestTask->off + pTestTask->DataSeg.cbSeg > pTestFile->cbFileCurr)
        pTestFile->cbFileCurr = pTestTask->off + pTestTask->DataSeg.cbSeg;

    AssertMsg(pTestFile->cbFileCurr <= pTestFile->cbFileMax,
              ("Current file size (%llu) exceeds final size (%llu)\n",
              pTestFile->cbFileCurr, pTestFile->cbFileMax));

    /* Allocate data buffer. */
    pTestTask->DataSeg.pvSeg = RTMemAlloc(pTestTask->DataSeg.cbSeg);
    if (!pTestTask->DataSeg.pvSeg)
        return VERR_NO_MEMORY;

    /* Fill data into buffer. */
    tstPDMACStressTestFileFillBuffer(pTestFile, pTestTask);

    /* Engage */
    rc = PDMR3AsyncCompletionEpWrite(pTestFile->hEndpoint, pTestTask->off,
                                     &pTestTask->DataSeg, 1,
                                     pTestTask->DataSeg.cbSeg,
                                     pTestTask,
                                     &pTestTask->hTask);

    return rc;
}
/**
 * Creates a TCP server that listens for the source machine and passes control
 * over to Console::teleporterTrgServeConnection().
 *
 * @returns VBox status code.
 * @param   pUVM                The user-mode VM handle
 * @param   pMachine            The IMachine for the virtual machine.
 * @param   pErrorMsg           Pointer to the error string for VMSetError.
 * @param   fStartPaused        Whether to start it in the Paused (true) or
 *                              Running (false) state,
 * @param   pProgress           Pointer to the progress object.
 * @param   pfPowerOffOnFailure Whether the caller should power off
 *                              the VM on failure.
 *
 * @remarks The caller expects error information to be set on failure.
 * @todo    Check that all the possible failure paths sets error info...
 */
HRESULT
Console::teleporterTrg(PUVM pUVM, IMachine *pMachine, Utf8Str *pErrorMsg, bool fStartPaused,
                       Progress *pProgress, bool *pfPowerOffOnFailure)
{
    LogThisFunc(("pUVM=%p pMachine=%p fStartPaused=%RTbool pProgress=%p\n", pUVM, pMachine, fStartPaused, pProgress));

    *pfPowerOffOnFailure = true;

    /*
     * Get the config.
     */
    ULONG uPort;
    HRESULT hrc = pMachine->COMGETTER(TeleporterPort)(&uPort);
    if (FAILED(hrc))
        return hrc;
    ULONG const uPortOrg = uPort;

    Bstr bstrAddress;
    hrc = pMachine->COMGETTER(TeleporterAddress)(bstrAddress.asOutParam());
    if (FAILED(hrc))
        return hrc;
    Utf8Str strAddress(bstrAddress);
    const char *pszAddress = strAddress.isEmpty() ? NULL : strAddress.c_str();

    Bstr bstrPassword;
    hrc = pMachine->COMGETTER(TeleporterPassword)(bstrPassword.asOutParam());
    if (FAILED(hrc))
        return hrc;
    Utf8Str strPassword(bstrPassword);
    strPassword.append('\n');           /* To simplify password checking. */

    /*
     * Create the TCP server.
     */
    int vrc;
    PRTTCPSERVER hServer;
    if (uPort)
        vrc = RTTcpServerCreateEx(pszAddress, uPort, &hServer);
    else
    {
        for (int cTries = 10240; cTries > 0; cTries--)
        {
            uPort = RTRandU32Ex(cTries >= 8192 ? 49152 : 1024, 65534);
            vrc = RTTcpServerCreateEx(pszAddress, uPort, &hServer);
            if (vrc != VERR_NET_ADDRESS_IN_USE)
                break;
        }
        if (RT_SUCCESS(vrc))
        {
            hrc = pMachine->COMSETTER(TeleporterPort)(uPort);
            if (FAILED(hrc))
            {
                RTTcpServerDestroy(hServer);
                return hrc;
            }
        }
    }
    if (RT_FAILURE(vrc))
        return setError(E_FAIL, tr("RTTcpServerCreateEx failed with status %Rrc"), vrc);

    /*
     * Create a one-shot timer for timing out after 5 mins.
     */
    RTTIMERLR hTimerLR;
    vrc = RTTimerLRCreateEx(&hTimerLR, 0 /*ns*/, RTTIMER_FLAGS_CPU_ANY, teleporterDstTimeout, hServer);
    if (RT_SUCCESS(vrc))
    {
        vrc = RTTimerLRStart(hTimerLR, 5*60*UINT64_C(1000000000) /*ns*/);
        if (RT_SUCCESS(vrc))
        {
            /*
             * Do the job, when it returns we're done.
             */
            TeleporterStateTrg theState(this, pUVM, pProgress, pMachine, mControl, &hTimerLR, fStartPaused);
            theState.mstrPassword      = strPassword;
            theState.mhServer          = hServer;

            void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(&theState));
            if (pProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser))
            {
                LogRel(("Teleporter: Waiting for incoming VM...\n"));
                hrc = pProgress->SetNextOperation(Bstr(tr("Waiting for incoming VM")).raw(), 1);
                if (SUCCEEDED(hrc))
                {
                    vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &theState);
                    pProgress->setCancelCallback(NULL, NULL);

                    if (vrc == VERR_TCP_SERVER_STOP)
                    {
                        vrc = theState.mRc;
                        /* Power off the VM on failure unless the state callback
                           already did that. */
                        *pfPowerOffOnFailure = false;
                        if (RT_SUCCESS(vrc))
                            hrc = S_OK;
                        else
                        {
                            VMSTATE enmVMState = VMR3GetStateU(pUVM);
                            if (    enmVMState != VMSTATE_OFF
                                    &&  enmVMState != VMSTATE_POWERING_OFF)
                                *pfPowerOffOnFailure = true;

                            /* Set error. */
                            if (pErrorMsg->length())
                                hrc = setError(E_FAIL, "%s", pErrorMsg->c_str());
                            else
                                hrc = setError(E_FAIL, tr("Teleporation failed (%Rrc)"), vrc);
                        }
                    }
                    else if (vrc == VERR_TCP_SERVER_SHUTDOWN)
                    {
                        BOOL fCanceled = TRUE;
                        hrc = pProgress->COMGETTER(Canceled)(&fCanceled);
                        if (FAILED(hrc) || fCanceled)
                            hrc = setError(E_FAIL, tr("Teleporting canceled"));
                        else
                            hrc = setError(E_FAIL, tr("Teleporter timed out waiting for incoming connection"));
                        LogRel(("Teleporter: RTTcpServerListen aborted - %Rrc\n", vrc));
                    }
                    else
                    {
                        hrc = setError(E_FAIL, tr("Unexpected RTTcpServerListen status code %Rrc"), vrc);
                        LogRel(("Teleporter: Unexpected RTTcpServerListen rc: %Rrc\n", vrc));
                    }
                }
                else
                    LogThisFunc(("SetNextOperation failed, %Rhrc\n", hrc));
            }
            else
            {
                LogThisFunc(("Canceled - check point #1\n"));
                hrc = setError(E_FAIL, tr("Teleporting canceled"));
            }
        }
        else
            hrc = setError(E_FAIL, "RTTimerLRStart -> %Rrc", vrc);

        RTTimerLRDestroy(hTimerLR);
    }
    else
        hrc = setError(E_FAIL, "RTTimerLRCreate -> %Rrc", vrc);
    RTTcpServerDestroy(hServer);

    /*
     * If we change TeleporterPort above, set it back to it's original
     * value before returning.
     */
    if (uPortOrg != uPort)
    {
        ErrorInfoKeeper Eik;
        pMachine->COMSETTER(TeleporterPort)(uPortOrg);
    }

    return hrc;
}