int main(int argc, char **argv) { RTTEST hTest; RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, 0 /*fRtInit*/, "tstRTIsoFs", &hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; if (argc <= 1) return RTTestSkipAndDestroy(hTest, "no input"); /* * First argument is the ISO to open. */ RTISOFSFILE IsoFs; int rc = RTIsoFsOpen(&IsoFs, argv[1]); if (RT_SUCCESS(rc)) { /* * Remaining arguments specifies files in the ISO that we wish information * about and optionally extract. */ for (int i = 2; i < argc; i++) { char *pszFile = argv[i]; char chSaved = 0; char *pszDst = strchr(pszFile, '='); if (pszDst) { chSaved = *pszDst; *pszDst = '\0'; } uint32_t offFile = UINT32_MAX / 2; size_t cbFile = UINT32_MAX / 2; rc = RTIsoFsGetFileInfo(&IsoFs, pszFile, &offFile, &cbFile); if (RT_SUCCESS(rc)) { RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%s: %u bytes at %#x\n", pszFile, (uint32_t)cbFile, offFile); if (pszDst) { rc = RTIsoFsExtractFile(&IsoFs, pszFile, pszDst); if (RT_SUCCESS(rc)) RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%s: saved as '%s'.\n", pszFile, pszDst); else RTTestFailed(hTest, "RTIsoFsExtractFile failed to extract '%s' to '%s': %Rrc", pszFile, pszDst, rc); } } else RTTestFailed(hTest, "RTIsoFsGetFileInfo failed for '%s': %Rrc", pszFile, rc); if (pszDst) pszDst[-1] = chSaved; } RTIsoFsClose(&IsoFs); } else RTTestFailed(hTest, "RTIsoFsOpen failed to open '%s': %Rrc", argv[1], rc); return RTTestSummaryAndDestroy(hTest); }
static int testSessionWait(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testSessionWait"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionWait", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest }; /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testSessionWaitThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc3"); if (RT_SUCCESS(rc)) { do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionWaitFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); RTThreadSleep(5000); /* Let the server run for some time ... */ RTTestPrintf(hTest, RTTESTLVL_INFO, "Cancelling server listening\n"); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS); /* Wait for the server thread to terminate. */ int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 30 * 1000 /* 30s timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VERR_CANCELLED); RTTEST_CHECK_RC(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n"); /* Check if the child ran successfully. */ RTPROCSTATUS stsChild; RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated\n"); RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL); RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0); } while (0); } else RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc); } else RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc); return VINF_SUCCESS; }
/** * Test execution worker. * * @returns nothing. * @param pszDevice The device to use for testing. */ static void usbTestExec(const char *pszDevice) { int iDevFd; RTTestSub(g_hTest, "Opening device"); iDevFd = open(pszDevice, O_RDWR); if (iDevFd != -1) { USBTESTPARAMS Params; RTTestPassed(g_hTest, "Opening device successful\n"); /* * Fill params with some defaults. * @todo: Make them configurable. */ Params.cIterations = 1000; Params.cbData = 512; Params.cbVariation = 512; Params.cSgLength = 32; for (unsigned i = 0; i < USBTEST_TEST_CASES; i++) { RTTestSub(g_hTest, g_apszTests[i]); Params.idxTest = i; /* Assume the test interface has the number 0 for now. */ int rcPosix = usbTestIoctl(iDevFd, 0, &Params); if (rcPosix < 0 && errno == EOPNOTSUPP) { RTTestSkipped(g_hTest, "Not supported"); continue; } if (rcPosix < 0) RTTestFailed(g_hTest, "Test failed with %Rrc\n", RTErrConvertFromErrno(errno)); else { uint64_t u64Ns = Params.TimeTest.tv_sec * RT_NS_1SEC + Params.TimeTest.tv_usec * RT_NS_1US; RTTestValue(g_hTest, "Runtime", u64Ns, RTTESTUNIT_NS); } RTTestSubDone(g_hTest); } close(iDevFd); } else RTTestFailed(g_hTest, "Opening device failed with %Rrc\n", RTErrConvertFromErrno(errno)); }
static void tstVfsIoFromStandardHandle(RTTEST hTest, RTHANDLESTD enmHandle) { RTTestSubF(hTest, "RTVfsIoStrmFromStdHandle(%s)", StandardHandleToString(enmHandle)); RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM; int rc = RTVfsIoStrmFromStdHandle(enmHandle, 0, true /*fLeaveOpen*/, &hVfsIos); if (RT_SUCCESS(rc)) { if ( enmHandle == RTHANDLESTD_OUTPUT || enmHandle == RTHANDLESTD_ERROR) { char szTmp[80]; size_t cchTmp = RTStrPrintf(szTmp, sizeof(szTmp), "Test output to %s\n", StandardHandleToString(enmHandle)); size_t cbWritten; RTTESTI_CHECK_RC(rc = RTVfsIoStrmWrite(hVfsIos, szTmp, cchTmp, true /*fBlocking*/, &cbWritten), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(cbWritten == cchTmp); } uint32_t cRefs = RTVfsIoStrmRelease(hVfsIos); RTTESTI_CHECK_MSG(cRefs == 0, ("cRefs=%#x\n", cRefs)); } else RTTestFailed(hTest, "Error creating VFS I/O stream for %s: %Rrc\n", StandardHandleToString(enmHandle), rc); }
/** * Some basic tests to detect malformed JSON. */ static void tstBasic(RTTEST hTest) { RTTestSub(hTest, "Basic valid/malformed tests"); static struct { const char *pszJson; int iRcResult; } const aTests[] = { { "", VERR_JSON_MALFORMED }, { ",", VERR_JSON_MALFORMED }, { ":", VERR_JSON_MALFORMED }, { " \n\t{", VERR_JSON_MALFORMED }, { "}", VERR_JSON_MALFORMED }, { "[", VERR_JSON_MALFORMED }, { "]", VERR_JSON_MALFORMED }, { "[ \"test\" : ", VERR_JSON_MALFORMED }, { "null", VINF_SUCCESS }, { "true", VINF_SUCCESS }, { "false", VINF_SUCCESS }, { "100", VINF_SUCCESS }, { "\"test\"", VINF_SUCCESS }, { "{ }", VINF_SUCCESS }, { "[ ]", VINF_SUCCESS }, { "[ 100, 200 ]", VINF_SUCCESS }, { "{ \"1\": 1 }", VINF_SUCCESS }, { "{ \"1\": 1, \"2\": 2 }", VINF_SUCCESS } }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(aTests); iTest++) { RTJSONVAL hJsonVal = NIL_RTJSONVAL; int rc = RTJsonParseFromString(&hJsonVal, aTests[iTest].pszJson, NULL); if (rc != aTests[iTest].iRcResult) RTTestFailed(hTest, "RTJsonParseFromString() for \"%s\" failed, expected %Rrc got %Rrc\n", aTests[iTest].pszJson, aTests[iTest].iRcResult, rc); if (RT_SUCCESS(rc)) { if (hJsonVal != NIL_RTJSONVAL) RTJsonValueRelease(hJsonVal); else RTTestFailed(hTest, "RTJsonParseFromString() returned success but no value\n"); } else if (hJsonVal != NIL_RTJSONVAL) RTTestFailed(hTest, "RTJsonParseFromString() failed but a JSON value was returned\n"); } }
/** * Tries one command string. * @param pDbgc Pointer to the debugger instance. * @param pszCmds The command to test. * @param rcCmd The expected result. * @param fNoExecute When set, the command is not executed. * @param pszExpected Expected output. This does not need to include all * of the output, just the start of it. Thus the * prompt can be omitted. */ static void tstTryEx(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected) { RT_ZERO(g_szOutput); g_offOutput = 0; g_pszInput = pszCmds; if (strchr(pszCmds, '\0')[-1] == '\n') RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds); else RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds); pDbgc->rcCmd = VERR_INTERNAL_ERROR; dbgcProcessInput(pDbgc, fNoExecute); tstCompleteOutput(); if (pDbgc->rcCmd != rcCmd) RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd); else if ( !fNoExecute && pszExpected && strncmp(pszExpected, g_szOutput, strlen(pszExpected))) RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected); }
static uint32_t test2AllocId(struct TestMap2 *p2) { /* * Scan sequentially from the last one + 1. */ int32_t idChunk = ++p2->idChunkPrev; if ( (uint32_t)idChunk < TEST2_ID_LAST && idChunk > NIL_TEST2_ID) { idChunk = ASMBitNextClear(&p2->bmChunkId[0], TEST2_ID_LAST + 1, idChunk); if (idChunk > NIL_TEST2_ID) { if (ASMAtomicBitTestAndSet(&p2->bmChunkId[0], idChunk)) { RTTestFailed(NIL_RTTEST, "line %d: idChunk=%#x", __LINE__, idChunk); return NIL_TEST2_ID; } return p2->idChunkPrev = idChunk; } } /* * Ok, scan from the start. */ idChunk = ASMBitFirstClear(&p2->bmChunkId[0], TEST2_ID_LAST + 1); if (idChunk <= NIL_TEST2_ID) { RTTestFailed(NIL_RTTEST, "line %d: idChunk=%#x", __LINE__, idChunk); return NIL_TEST2_ID; } if (ASMAtomicBitTestAndSet(&p2->bmChunkId[0], idChunk)) { RTTestFailed(NIL_RTTEST, "line %d: idChunk=%#x", __LINE__, idChunk); return NIL_TEST2_ID; } return p2->idChunkPrev = idChunk; }
/** * Test that the parser returns the correct values for a valid JSON. */ static void tstCorrectness(RTTEST hTest) { RTTestSub(hTest, "Correctness"); RTJSONVAL hJsonVal = NIL_RTJSONVAL; RTTEST_CHECK_RC_OK_RETV(hTest, RTJsonParseFromString(&hJsonVal, g_pszJson, NULL)); if (hJsonVal != NIL_RTJSONVAL) { RTJSONVALTYPE enmType = RTJsonValueGetType(hJsonVal); if (enmType == RTJSONVALTYPE_OBJECT) { /* Excercise the other non object APIs to return VERR_JSON_VALUE_INVALID_TYPE. */ tstCorrectnessRcForInvalidType(hTest, hJsonVal, enmType); tstIterator(hTest, hJsonVal); } else RTTestFailed(hTest, "RTJsonParseFromString() returned an invalid JSON value, expected OBJECT got %u\n", enmType); RTTEST_CHECK(hTest, RTJsonValueRelease(hJsonVal) == 0); } else RTTestFailed(hTest, "RTJsonParseFromString() returned success but no value\n"); }
int main() { RTTEST hTest; RTEXITCODE rcExit = RTTestInitAndCreate("tstRTErrUnique", &hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; RTTestBanner(hTest); RTTestSub(hTest, "IPRT status code"); for (uint32_t i = 0; i < RT_ELEMENTS(g_aErrorMessages) - 1; i++) if (!strIsPermissibleDuplicate(&g_aErrorMessages[i])) for (uint32_t j = i + 1; j < RT_ELEMENTS(g_aErrorMessages); j++) if ( !strIsPermissibleDuplicate(&g_aErrorMessages[j]) && g_aErrorMessages[i].iCode == g_aErrorMessages[j].iCode) RTTestFailed(hTest, "Status code %d can mean both '%s' and '%s'", g_aErrorMessages[i].iCode, g_aErrorMessages[i].pszDefine, g_aErrorMessages[j].pszDefine); return RTTestSummaryAndDestroy(hTest); }
int main(int argc, char **argv) { #ifndef VBOX RTPrintf("tstSup: SKIPPED\n"); return 0; #else /* * Init. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstR0ThreadPreemption", &hTest); if (rc) return rc; RTTestBanner(hTest); PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } char szPath[RTPATH_MAX]; rc = RTPathExecDir(szPath, sizeof(szPath)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szPath, sizeof(szPath), "tstR0ThreadPreemption.r0"); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "Failed constructing .r0 filename (rc=%Rrc)", rc); return RTTestSummaryAndDestroy(hTest); } void *pvImageBase; rc = SUPR3LoadServiceModule(szPath, "tstR0ThreadPreemption", "TSTR0ThreadPreemptionSrvReqHandler", &pvImageBase); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3LoadServiceModule(%s,,,) failed with rc=%Rrc\n", szPath, rc); return RTTestSummaryAndDestroy(hTest); } /* test request */ struct { SUPR0SERVICEREQHDR Hdr; char szMsg[256]; } Req; /* * Sanity checks. */ RTTestSub(hTest, "Sanity"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_SANITY_OK, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(Req.szMsg[0] == '\0', ("%s", Req.szMsg)); if (Req.szMsg[0] != '\0') return RTTestSummaryAndDestroy(hTest); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_SANITY_FAILURE, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(!strncmp(Req.szMsg, "!42failure42", sizeof("!42failure42") - 1), ("%s", Req.szMsg)); if (strncmp(Req.szMsg, "!42failure42", sizeof("!42failure42") - 1)) return RTTestSummaryAndDestroy(hTest); /* * Basic tests, bail out on failure. */ RTTestSub(hTest, "Basics"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_BASIC, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); if (Req.szMsg[0] == '!') { RTTestIFailed("%s", &Req.szMsg[1]); return RTTestSummaryAndDestroy(hTest); } if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); /* * Stay in ring-0 until preemption is pending. */ RTThreadSleep(250); /** @todo fix GIP initialization? */ RTTestSub(hTest, "Pending Preemption"); for (int i = 0; ; i++) { Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_IS_PENDING, 0, &Req.Hdr), VINF_SUCCESS); if ( strcmp(Req.szMsg, "cLoops=1\n") || i >= 64) { if (Req.szMsg[0] == '!') RTTestIFailed("%s", &Req.szMsg[1]); else if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); break; } if ((i % 3) == 0) RTThreadYield(); } /* * Test nested RTThreadPreemptDisable calls. */ RTTestSub(hTest, "Nested"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_NESTED, 0, &Req.Hdr), VINF_SUCCESS); if (Req.szMsg[0] == '!') RTTestIFailed("%s", &Req.szMsg[1]); else if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); /* * Done. */ return RTTestSummaryAndDestroy(hTest); #endif }
static int testSessionConnection(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testSessionConnection"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionConnection", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { #ifndef VBOX_TESTCASES_WITH_NO_THREADING LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest }; /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testSessionConnectionThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc2"); if (RT_SUCCESS(rc)) { do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionConnectionFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); RTPROCSTATUS stsChild; RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated, waiting for server thread ...\n"); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS); int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 30 * 1000 /* 30s timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VERR_CANCELLED); RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n"); RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL); RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0); } while (0); } else RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc); #else do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionConnectionFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); RTLOCALIPCSESSION ipcSession; rc = RTLocalIpcServerListen(ipcServer, &ipcSession); if (RT_SUCCESS(rc)) { RTTestPrintf(hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Got new client connection\n"); } else RTTestFailed(hTest, "Error while listening, rc=%Rrc\n", rc); } while (0); #endif } else RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc); return VINF_SUCCESS; }
static void testParserAndSplitter(RTTEST hTest) { static struct { uint16_t cComps; uint16_t cchPath; uint16_t offSuffix; const char *pszPath; uint16_t fProps; uint32_t fFlags; } const s_aTests[] = { { 2, 5, 5, "/bin/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_DIR_SLASH, RTPATH_STR_F_STYLE_UNIX }, { 2, 13, 9, "C:/Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_DOS }, { 2, 13, 10, "C://Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_DOS }, { 2, 12, 8, "C:Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_DOS }, { 1, 10, 6, "Config.sys", RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_DOS }, { 1, 4, 4, "//./", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE, RTPATH_STR_F_STYLE_DOS }, { 2, 5, 5, "//./f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_DOS }, { 2, 5, 6, "//.//f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_DOS }, { 3, 7, 7, "//././f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS, RTPATH_STR_F_STYLE_DOS }, { 3, 8, 8, "//.././f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS, RTPATH_STR_F_STYLE_DOS }, { 3, 9, 9, "//../../f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOTDOT_REFS, RTPATH_STR_F_STYLE_DOS }, { 1, 1, 1, "/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE, RTPATH_STR_F_STYLE_UNIX }, { 2, 4, 4, "/bin", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 2, 5, 5, "/bin/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_DIR_SLASH, RTPATH_STR_F_STYLE_UNIX }, { 3, 7, 7, "/bin/ls", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 3, 12, 7, "/etc/rc.conf", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_UNIX }, { 1, 1, 2, "//", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_UNIX }, { 1, 1, 3, "///", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_UNIX }, { 3, 6, 7, "/.//bin", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_DOT_REFS | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 1, 3, 3, "bin", RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 1, 4, 4, "bin/", RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH, RTPATH_STR_F_STYLE_UNIX }, { 1, 4, 7, "bin////", RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_UNIX }, { 3, 10, 10, "bin/../usr", RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 11, 11, "/bin/../usr", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.../u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.b./u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/..c/u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/d../u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.e/.u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.f/.u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.g/u.", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 3, 9, 10, "/a/h/u.ext", RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_MIDDLE }, { 3, 9, 9, "a/h/u.ext", RTPATH_PROP_RELATIVE, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_MIDDLE }, { 3, 9, 10, "a/h/u.ext/", RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_MIDDLE }, }; char szPath1[RTPATH_MAX]; union { RTPATHPARSED Parsed; RTPATHSPLIT Split; uint8_t ab[4096]; } u; RTTestSub(hTest, "RTPathParse"); for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++) { memset(&u, i & 1 ? 0xff : 0, sizeof(u)); int rc = RTPathParse(s_aTests[i].pszPath, &u.Parsed, sizeof(u), s_aTests[i].fFlags); if ( rc != VINF_SUCCESS || s_aTests[i].cComps != u.Parsed.cComps || s_aTests[i].fProps != u.Parsed.fProps || s_aTests[i].offSuffix != u.Parsed.offSuffix || s_aTests[i].cchPath != u.Parsed.cchPath) { RTTestFailed(hTest, "i=%d rc=%Rrc %s", i, rc, s_aTests[i].pszPath); RTTestFailureDetails(hTest, " cComps %u, got %u\n" " fProps %#x, got %#x, xor=>%#x\n" " offSuffix %u, got %u\n" " cchPath %u, got %u\n" , s_aTests[i].cComps, u.Parsed.cComps, s_aTests[i].fProps, u.Parsed.fProps, s_aTests[i].fProps ^ u.Parsed.fProps, s_aTests[i].offSuffix, u.Parsed.offSuffix, s_aTests[i].cchPath, u.Parsed.cchPath); } else { rc = RTPathParsedReassemble(s_aTests[i].pszPath, &u.Parsed, s_aTests[i].fFlags & ~RTPATH_STR_F_MIDDLE, szPath1, sizeof(szPath1)); if (rc == VINF_SUCCESS) { RTTESTI_CHECK_MSG(strlen(szPath1) == s_aTests[i].cchPath, ("%s\n", szPath1)); if ( !(u.Parsed.fProps & RTPATH_PROP_EXTRA_SLASHES) && (s_aTests[i].fFlags & RTPATH_STR_F_STYLE_MASK) != RTPATH_STR_F_STYLE_DOS) RTTESTI_CHECK_MSG(strcmp(szPath1, s_aTests[i].pszPath) == 0, ("%s\n", szPath1)); } else RTTestIFailed("RTPathParsedReassemble -> %Rrc", rc); } } RTTestSub(hTest, "RTPathSplit"); for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++) { memset(&u, i & 1 ? 0xff : 0, sizeof(u)); int rc = RTPathSplit(s_aTests[i].pszPath, &u.Split, sizeof(u), s_aTests[i].fFlags); if ( rc != VINF_SUCCESS || s_aTests[i].cComps != u.Split.cComps || s_aTests[i].fProps != u.Split.fProps || s_aTests[i].cchPath != u.Split.cchPath) { RTTestFailed(hTest, "i=%d rc=%Rrc %s", i, rc, s_aTests[i].pszPath); RTTestFailureDetails(hTest, " cComps %u, got %u\n" " fProps %#x, got %#x, xor=>%#x\n" " cchPath %u, got %u\n" , s_aTests[i].cComps, u.Split.cComps, s_aTests[i].fProps, u.Split.fProps, s_aTests[i].fProps ^ u.Split.fProps, s_aTests[i].cchPath, u.Split.cchPath); } else { RTTESTI_CHECK_MSG(*u.Split.pszSuffix == '\0' || *u.Split.pszSuffix == '.', ("%s", u.Split.pszSuffix)); for (uint32_t idxComp = RTPATH_PROP_HAS_ROOT_SPEC(u.Split.fProps); idxComp < u.Split.cComps; idxComp++) if ( (s_aTests[i].fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_DOS ? strpbrk(u.Split.apszComps[idxComp], "/\\") : strchr(u.Split.apszComps[idxComp], RTPATH_SLASH) ) RTTestFailed(hTest, "i=%d idxComp=%d '%s'", i, idxComp, u.Split.apszComps[idxComp]); PRTPATHSPLIT pSplit = NULL; RTTESTI_CHECK_RC(rc = RTPathSplitA(s_aTests[i].pszPath, &pSplit, s_aTests[i].fFlags), VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK(pSplit); RTTESTI_CHECK(pSplit->cComps == u.Split.cComps); RTTESTI_CHECK(pSplit->fProps == u.Split.fProps); RTTESTI_CHECK(pSplit->cchPath == u.Split.cchPath); RTTESTI_CHECK(pSplit->cbNeeded == u.Split.cbNeeded); RTTESTI_CHECK(!strcmp(pSplit->pszSuffix, u.Split.pszSuffix)); for (uint32_t idxComp = 0; idxComp < u.Split.cComps; idxComp++) RTTESTI_CHECK(!strcmp(pSplit->apszComps[idxComp], pSplit->apszComps[idxComp])); RTPathSplitFree(pSplit); } rc = RTPathSplitReassemble(&u.Split, s_aTests[i].fFlags & ~RTPATH_STR_F_MIDDLE, szPath1, sizeof(szPath1)); if (rc == VINF_SUCCESS) { RTTESTI_CHECK_MSG(strlen(szPath1) == s_aTests[i].cchPath, ("%s\n", szPath1)); if ( !(u.Parsed.fProps & RTPATH_PROP_EXTRA_SLASHES) && (s_aTests[i].fFlags & RTPATH_STR_F_STYLE_MASK) != RTPATH_STR_F_STYLE_DOS) RTTESTI_CHECK_MSG(strcmp(szPath1, s_aTests[i].pszPath) == 0, ("%s\n", szPath1)); } else RTTestIFailed("RTPathSplitReassemble -> %Rrc", rc); } } }
int main() { /* * Set up the test environment. */ RTTEST hTest; RTEXITCODE rcExit = RTTestInitAndCreate("tstX86-1", &hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; RTTestBanner(hTest); g_pbEfPage = (uint8_t *)RTTestGuardedAllocTail(hTest, PAGE_SIZE); RTTESTI_CHECK(g_pbEfPage != NULL); g_pbEfExecPage = (uint8_t *)RTMemExecAlloc(PAGE_SIZE*2); RTTESTI_CHECK(g_pbEfExecPage != NULL); RTTESTI_CHECK(!((uintptr_t)g_pbEfExecPage & PAGE_OFFSET_MASK)); RTTESTI_CHECK_RC(RTMemProtect(g_pbEfExecPage + PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_NONE), VINF_SUCCESS); #ifdef USE_SIGNAL static int const s_aiSigs[] = { SIGBUS, SIGSEGV, SIGFPE, SIGILL }; for (unsigned i = 0; i < RT_ELEMENTS(s_aiSigs); i++) { struct sigaction SigAct; RTTESTI_CHECK_BREAK(sigaction(s_aiSigs[i], NULL, &SigAct) == 0); SigAct.sa_sigaction = sigHandler; SigAct.sa_flags |= SA_SIGINFO; RTTESTI_CHECK(sigaction(s_aiSigs[i], &SigAct, NULL) == 0); } #else /** @todo implement me. */ #endif if (!RTTestErrorCount(hTest)) { /* * Do the testing. */ int32_t rc; #if 0 RTTestSub(hTest, "Misc 1"); rc = x861_Test1(); if (rc != 0) RTTestFailed(hTest, "x861_Test1 -> %d", rc); RTTestSub(hTest, "Prefixes and groups"); rc = x861_Test2(); if (rc != 0) RTTestFailed(hTest, "x861_Test2 -> %d", rc); RTTestSub(hTest, "fxsave / fxrstor and #PFs"); rc = x861_Test3(); if (rc != 0) RTTestFailed(hTest, "x861_Test3 -> %d", rc); RTTestSub(hTest, "Multibyte NOPs"); rc = x861_Test4(); if (rc != 0) RTTestFailed(hTest, "x861_Test4 -> %d", rc); //#endif RTTestSub(hTest, "Odd encodings and odd ends"); rc = x861_Test5(); if (rc != 0) RTTestFailed(hTest, "x861_Test5 -> %d", rc); //#if 0 RTTestSub(hTest, "Odd floating point encodings"); rc = x861_Test6(); if (rc != 0) RTTestFailed(hTest, "x861_Test5 -> %d", rc); RTTestSub(hTest, "Floating point exceptions ++"); rc = x861_Test7(); if (rc != 0) RTTestFailed(hTest, "x861_Test6 -> %d", rc); #endif rc = x861_TestFPUInstr1(); if (rc != 0) RTTestFailed(hTest, "x861_TestFPUInstr1 -> %d", rc); } return RTTestSummaryAndDestroy(hTest); }
static void Test4(unsigned cThreads, unsigned cSeconds, unsigned uWritePercent, bool fYield, bool fQuiet) { unsigned i; uint64_t acIterations[32]; RTTHREAD aThreads[RT_ELEMENTS(acIterations)]; AssertRelease(cThreads <= RT_ELEMENTS(acIterations)); RTTestSubF(g_hTest, "Test4 - %u threads, %u sec, %u%% writes, %syielding", cThreads, cSeconds, uWritePercent, fYield ? "" : "non-"); /* * Init globals. */ g_fYield = fYield; g_fQuiet = fQuiet; g_fTerminate = false; g_uWritePercent = uWritePercent; g_cConcurrentWriters = 0; g_cConcurrentReaders = 0; RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectRwInit(&g_CritSectRw), VINF_SUCCESS); /* * Create the threads and let them block on the semrw. */ RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectRwEnterExcl(&g_CritSectRw), VINF_SUCCESS); for (i = 0; i < cThreads; i++) { acIterations[i] = 0; RTTEST_CHECK_RC_RETV(g_hTest, RTThreadCreateF(&aThreads[i], Test4Thread, &acIterations[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test-%u", i), VINF_SUCCESS); } /* * Do the test run. */ uint32_t cErrorsBefore = RTTestErrorCount(g_hTest); uint64_t u64StartTS = RTTimeNanoTS(); RTTEST_CHECK_RC(g_hTest, RTCritSectRwLeaveExcl(&g_CritSectRw), VINF_SUCCESS); RTThreadSleep(cSeconds * 1000); ASMAtomicWriteBool(&g_fTerminate, true); uint64_t ElapsedNS = RTTimeNanoTS() - u64StartTS; /* * Clean up the threads and semaphore. */ for (i = 0; i < cThreads; i++) RTTEST_CHECK_RC(g_hTest, RTThreadWait(aThreads[i], 5000, NULL), VINF_SUCCESS); RTTEST_CHECK_MSG(g_hTest, g_cConcurrentWriters == 0, (g_hTest, "g_cConcurrentWriters=%u at end of test\n", g_cConcurrentWriters)); RTTEST_CHECK_MSG(g_hTest, g_cConcurrentReaders == 0, (g_hTest, "g_cConcurrentReaders=%u at end of test\n", g_cConcurrentReaders)); RTTEST_CHECK_RC(g_hTest, RTCritSectRwDelete(&g_CritSectRw), VINF_SUCCESS); if (RTTestErrorCount(g_hTest) != cErrorsBefore) RTThreadSleep(100); /* * Collect and display the results. */ uint64_t cItrTotal = acIterations[0]; for (i = 1; i < cThreads; i++) cItrTotal += acIterations[i]; uint64_t cItrNormal = cItrTotal / cThreads; uint64_t cItrMinOK = cItrNormal / 20; /* 5% */ uint64_t cItrMaxDeviation = 0; for (i = 0; i < cThreads; i++) { uint64_t cItrDelta = RT_ABS((int64_t)(acIterations[i] - cItrNormal)); if (acIterations[i] < cItrMinOK) RTTestFailed(g_hTest, "Thread %u did less than 5%% of the iterations - %llu (it) vs. %llu (5%%) - %llu%%\n", i, acIterations[i], cItrMinOK, cItrDelta * 100 / cItrNormal); else if (cItrDelta > cItrNormal / 2) RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Warning! Thread %u deviates by more than 50%% - %llu (it) vs. %llu (avg) - %llu%%\n", i, acIterations[i], cItrNormal, cItrDelta * 100 / cItrNormal); if (cItrDelta > cItrMaxDeviation) cItrMaxDeviation = cItrDelta; } //RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, // "Threads: %u Total: %llu Per Sec: %llu Avg: %llu ns Max dev: %llu%%\n", // cThreads, // cItrTotal, // cItrTotal / cSeconds, // ElapsedNS / cItrTotal, // cItrMaxDeviation * 100 / cItrNormal // ); // RTTestValue(g_hTest, "Thruput", cItrTotal * UINT32_C(1000000000) / ElapsedNS, RTTESTUNIT_CALLS_PER_SEC); RTTestValue(g_hTest, "Max diviation", cItrMaxDeviation * 100 / cItrNormal, RTTESTUNIT_PCT); }
int main() { /* * Init the runtime and stuff. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstFork", &hTest); if (rc) return rc; RTTestBanner(hTest); #ifdef RT_OS_WINDOWS RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Skipped\n"); #else /* * Get values that are supposed to or change across the fork. */ RTPROCESS const ProcBefore = RTProcSelf(); /* * Fork. */ pid_t pid = fork(); if (pid == 0) { /* * Check that the values has changed. */ rc = 0; if (ProcBefore == RTProcSelf()) { RTTestFailed(hTest, "%RTproc == %RTproc [child]", ProcBefore, RTProcSelf()); rc = 1; } return rc; } if (pid != -1) { /* * Check that the values didn't change. */ RTTEST_CHECK(hTest, ProcBefore == RTProcSelf()); /* * Wait for the child. */ rc = 1; while ( waitpid(pid, &rc, 0) && errno == EINTR) rc = 1; if (!WIFEXITED(rc) || WEXITSTATUS(rc) != 0) RTTestFailed(hTest, "rc=%#x", rc); } else RTTestFailed(hTest, "fork() failed: %d - %s", errno, strerror(errno)); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
static int testSessionData(RTTEST hTest, const char *pszExecPath) { RTTestSub(hTest, "testSessionData"); RTLOCALIPCSERVER ipcServer; int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionData", RTLOCALIPC_FLAGS_MULTI_SESSION); if (RT_SUCCESS(rc)) { LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest }; #if 0 /* Run server + client in threads instead of fork'ed processes (useful for debugging). */ RTTHREAD hThreadServer, hThreadClient; rc = RTThreadCreate(&hThreadServer, testSessionDataThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc4"); if (RT_SUCCESS(rc)) rc = RTThreadCreate(&hThreadClient, testSessionDataChildAsThread, &hTest, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc5"); if (RT_SUCCESS(rc)) { do { int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThreadServer, 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS); RTTEST_CHECK_RC(hTest, RTThreadWait(hThreadClient, 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS); } while (0); } #else /* Spawn a simple worker thread and let it listen for incoming connections. * In the meanwhile we try to cancel the server and see what happens. */ RTTHREAD hThread; rc = RTThreadCreate(&hThread, testSessionDataThread, &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc4"); if (RT_SUCCESS(rc)) { do { RTPROCESS hProc; const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionDataFork", NULL }; RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS); /* Wait for the server thread to terminate. */ int threadRc; RTTEST_CHECK_RC(hTest, RTThreadWait(hThread, 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS); RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS); RTTEST_CHECK_RC(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n"); /* Check if the child ran successfully. */ RTPROCSTATUS stsChild; RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS); RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated\n"); RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL); RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0); } while (0); } else RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc); #endif } else RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc); return !RTTestErrorCount(hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */; }
int main(int argc, char **argv) { /* * Init runtime and the test environment. */ int rc = RTR3InitAndSUPLib(); if (RT_FAILURE(rc)) { RTPrintf("tstVMM: RTR3InitAndSUPLib failed: %Rrc\n", rc); return 1; } RTTEST hTest; rc = RTTestCreate("tstVMM", &hTest); if (RT_FAILURE(rc)) { RTPrintf("tstVMM: RTTestCreate failed: %Rrc\n", rc); return 1; } /* * Parse arguments. */ static const RTGETOPTDEF s_aOptions[] = { { "--cpus", 'c', RTGETOPT_REQ_UINT8 }, { "--test", 't', RTGETOPT_REQ_STRING }, }; enum { kTstVMMTest_VMM, kTstVMMTest_TM } enmTestOpt = kTstVMMTest_VMM; int ch; int i = 1; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 'c': g_cCpus = ValueUnion.u8; break; case 't': if (!strcmp("vmm", ValueUnion.psz)) enmTestOpt = kTstVMMTest_VMM; else if (!strcmp("tm", ValueUnion.psz)) enmTestOpt = kTstVMMTest_TM; else { RTPrintf("tstVMM: unknown test: '%s'\n", ValueUnion.psz); return 1; } break; case 'h': RTPrintf("usage: tstVMM [--cpus|-c cpus] [--test <vmm|tm>]\n"); return 1; case 'V': RTPrintf("$Revision: $\n"); return 0; default: return RTGetOptPrintError(ch, &ValueUnion); } } /* * Create the test VM. */ RTPrintf(TESTCASE ": Initializing...\n"); PVM pVM; rc = VMR3Create(g_cCpus, NULL, NULL, NULL, tstVMMConfigConstructor, NULL, &pVM); if (RT_SUCCESS(rc)) { PDMR3LdrEnumModules(pVM, tstVMMLdrEnum, NULL); RTStrmFlush(g_pStdOut); RTThreadSleep(256); /* * Do the requested testing. */ switch (enmTestOpt) { case kTstVMMTest_VMM: { RTTestSub(hTest, "VMM"); rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc); break; } case kTstVMMTest_TM: { RTTestSub(hTest, "TM"); for (VMCPUID idCpu = 1; idCpu < g_cCpus; idCpu++) { rc = VMR3ReqCallNoWait(pVM, idCpu, (PFNRT)tstTMWorker, 2, pVM, hTest); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMR3ReqCall failed: rc=%Rrc\n", rc); } rc = VMR3ReqCallWait(pVM, 0 /*idDstCpu*/, (PFNRT)tstTMWorker, 2, pVM, hTest); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc); break; } } STAMR3Dump(pVM, "*"); /* * Cleanup. */ rc = VMR3PowerOff(pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMR3PowerOff failed: rc=%Rrc\n", rc); rc = VMR3Destroy(pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMR3Destroy failed: rc=%Rrc\n", rc); } else RTTestFailed(hTest, "VMR3Create failed: rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); }
int main() { RTTEST hTest; int rc = RTTestInitAndCreate("tstRTStrVersion", &hTest); if (rc) return rc; RTTestBanner(hTest); RTTestSub(hTest, "RTStrVersionCompare"); static struct { const char *pszVer1; const char *pszVer2; int iResult; } const aTests[] = { { "", "", 0 }, { "asdf", "", 1 }, { "asdf234", "1.4.5", 1 }, { "12.foo006", "12.6", 1 }, { "1", "1", 0 }, { "1", "100", -1}, { "100", "1", 1 }, { "3", "4", -1}, { "1", "0.1", 1 }, { "1", "0.0.0.0.10000", 1 }, { "0100", "100", 0 }, { "1.0.0", "1", 0 }, { "1.0.0", "100.0.0", -1}, { "1", "1.0.3.0", -1}, { "1.4.5", "1.2.3", 1 }, { "1.2.3", "1.4.5", -1}, { "1.2.3", "4.5.6", -1}, { "1.0.4", "1.0.3", 1 }, { "0.1", "0.0.1", 1 }, { "0.0.1", "0.1.1", -1}, { "3.1.0", "3.0.14", 1 }, { "2.0.12", "3.0.14", -1}, { "3.1", "3.0.22", 1 }, { "3.0.14", "3.1.0", -1}, { "45.63", "04.560.30", 1 }, { "45.006", "45.6", 0 }, { "23.206", "23.06", 1 }, { "23.2", "23.060", -1}, { "VirtualBox-2.0.8-Beta2", "VirtualBox-2.0.8_Beta3-r12345", -1 }, { "VirtualBox-2.2.4-Beta2", "VirtualBox-2.2.2", 1 }, { "VirtualBox-2.2.4-Beta3", "VirtualBox-2.2.2-Beta4", 1 }, { "VirtualBox-3.1.8-Alpha1", "VirtualBox-3.1.8-Alpha1-r61454", -1 }, { "VirtualBox-3.1.0", "VirtualBox-3.1.2_Beta1", -1 }, { "3.1.0_BETA-r12345", "3.1.2", -1 }, { "3.1.0_BETA1r12345", "3.1.0", -1 }, { "3.1.0_BETAr12345", "3.1.0", -1 }, { "3.1.0_BETA-r12345", "3.1.0", -1 }, { "3.1.0_BETA-r12345", "3.1.0", -1 }, { "3.1.0_BETA-r12345", "3.1.0.0", -1 }, { "3.1.0_BETA", "3.1.0.0", -1 }, { "3.1.0_BETA1", "3.1.0", -1 }, { "3.1.0_BETA-r12345", "3.1.0r12345", -1 }, { "3.1.0_BETA1-r12345", "3.1.0_BETA-r12345", 0 }, { "3.1.0_BETA1-r12345", "3.1.0_BETA1-r12345", 0 }, { "3.1.0_BETA2-r12345", "3.1.0_BETA1-r12345", 1 }, { "3.1.0_BETA2-r12345", "3.1.0_BETA999-r12345", -1 }, { "3.1.0_BETA2", "3.1.0_ABC", -1 }, /* ABC isn't indicating a prerelease, BETA does. */ { "3.1.0_BETA", "3.1.0_ATEB", -1 }, { "4.0.0_ALPHAr68482", "4.0.0_ALPHAr68483", -1 }, { "4.0.0_ALPHA1r68482", "4.0.0_ALPHAr68482", 0 }, { "4.0.0_ALPHA-r68482", "4.0.0_ALPHAr68482", 0 }, { "4.0.0_ALPHAr68483", "4.0.0_BETAr68783", -1 }, { "4.0.0_ALPHAr68483", "4.0.0_BETA1r68783", -1 }, { "4.0.0_ALPHAr68483", "4.0.0_BETA2r68783", -1 }, { "4.0.0_ALPHAr68483", "4.0.0_BETA2r68784", -1 }, { "4.0.6", "4.0.6_Ubuntu", -1 }, /* Without stripped guest OS string (Ubuntu). */ { "4.0.6_Windows", "4.0.6", 1 } /* Without stripped guest OS string (Windows). */ }; for (unsigned iTest = 0; iTest < RT_ELEMENTS(aTests); iTest++) { int iResult = RTStrVersionCompare(aTests[iTest].pszVer1, aTests[iTest].pszVer2); if (iResult != aTests[iTest].iResult) RTTestFailed(hTest, "#%u: '%s' <-> '%s' -> %d, expected %d", iTest, aTests[iTest].pszVer1, aTests[iTest].pszVer2, iResult, aTests[iTest].iResult); iResult = -RTStrVersionCompare(aTests[iTest].pszVer2, aTests[iTest].pszVer1); if (iResult != aTests[iTest].iResult) RTTestFailed(hTest, "#%u: '%s' <-> '%s' -> %d, expected %d [inv]", iTest, aTests[iTest].pszVer1, aTests[iTest].pszVer2, iResult, aTests[iTest].iResult); } /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }
/** * Tests the iterator API for the given JSON array or object value. */ static void tstIterator(RTTEST hTest, RTJSONVAL hJsonVal) { RTJSONIT hJsonIt = NIL_RTJSONIT; int rc = RTJsonIteratorBegin(hJsonVal, &hJsonIt); RTTEST_CHECK(hTest, RT_SUCCESS(rc)); if (RT_SUCCESS(rc)) { const char *pszName = NULL; RTJSONVAL hJsonValMember = NIL_RTJSONVAL; rc = RTJsonIteratorQueryValue(hJsonIt, &hJsonValMember, &pszName); RTTEST_CHECK(hTest, RT_SUCCESS(rc)); RTTEST_CHECK(hTest, pszName != NULL); RTTEST_CHECK(hTest, hJsonValMember != NIL_RTJSONVAL); while (RT_SUCCESS(rc)) { RTJSONVALTYPE enmTypeMember = RTJsonValueGetType(hJsonValMember); tstCorrectnessRcForInvalidType(hTest, hJsonValMember, enmTypeMember); switch (enmTypeMember) { case RTJSONVALTYPE_OBJECT: RTTEST_CHECK(hTest, strcmp(pszName, "subobject") == 0); tstIterator(hTest, hJsonValMember); break; case RTJSONVALTYPE_ARRAY: RTTEST_CHECK(hTest, strcmp(pszName, "array") == 0); tstArray(hTest, hJsonValMember); break; case RTJSONVALTYPE_STRING: { RTTEST_CHECK(hTest, strcmp(pszName, "string") == 0); const char *pszStr = NULL; RTTEST_CHECK_RC_OK(hTest, RTJsonValueQueryString(hJsonValMember, &pszStr)); RTTEST_CHECK(hTest, strcmp(pszStr, "test") == 0); break; } case RTJSONVALTYPE_NUMBER: { RTTEST_CHECK(hTest, strcmp(pszName, "number") == 0); int64_t i64Num = 0; RTTEST_CHECK_RC_OK(hTest, RTJsonValueQueryInteger(hJsonValMember, &i64Num)); RTTEST_CHECK(hTest, i64Num == 100); break; } case RTJSONVALTYPE_NULL: RTTEST_CHECK(hTest, strcmp(pszName, "null") == 0); break; case RTJSONVALTYPE_TRUE: RTTEST_CHECK(hTest, strcmp(pszName, "true") == 0); break; case RTJSONVALTYPE_FALSE: RTTEST_CHECK(hTest, strcmp(pszName, "false") == 0); break; default: RTTestFailed(hTest, "Invalid JSON value type %u returned\n", enmTypeMember); } RTTEST_CHECK(hTest, RTJsonValueRelease(hJsonValMember) == 1); rc = RTJsonIteratorNext(hJsonIt); RTTEST_CHECK(hTest, rc == VINF_SUCCESS || rc == VERR_JSON_ITERATOR_END); if (RT_SUCCESS(rc)) RTTEST_CHECK_RC_OK(hTest, RTJsonIteratorQueryValue(hJsonIt, &hJsonValMember, &pszName)); } RTJsonIteratorFree(hJsonIt); } }
/** * Tries one command string. * @param pDbgc Pointer to the debugger instance. * @param pszCmds The command to test. * @param rcCmd The expected result. * @param fNoExecute When set, the command is not executed. * @param pszExpected Expected output. This does not need to include all * of the output, just the start of it. Thus the * prompt can be omitted. * @param cArgs The number of expected arguments. -1 if we don't * want to check the parsed arguments. * @param va Info about expected parsed arguments. For each * argument a DBGCVARTYPE, value (depends on type), * DBGCVARRANGETYPE and optionally range value. */ static void tstTryExV(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected, int32_t cArgs, va_list va) { RT_ZERO(g_szOutput); g_offOutput = 0; g_pszInput = pszCmds; if (strchr(pszCmds, '\0')[-1] == '\n') RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds); else RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds); pDbgc->rcCmd = VERR_INTERNAL_ERROR; dbgcProcessInput(pDbgc, fNoExecute); tstCompleteOutput(); if (pDbgc->rcCmd != rcCmd) RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd); else if ( !fNoExecute && pszExpected && strncmp(pszExpected, g_szOutput, strlen(pszExpected))) RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected); if (cArgs >= 0) { PCDBGCVAR paArgs = pDbgc->aArgs; for (int32_t iArg = 0; iArg < cArgs; iArg++) { DBGCVAR ExpectedArg; ExpectedArg.enmType = (DBGCVARTYPE)va_arg(va, int/*DBGCVARTYPE*/); switch (ExpectedArg.enmType) { case DBGCVAR_TYPE_GC_FLAT: ExpectedArg.u.GCFlat = va_arg(va, RTGCPTR); break; case DBGCVAR_TYPE_GC_FAR: ExpectedArg.u.GCFar.sel = va_arg(va, int /*RTSEL*/); ExpectedArg.u.GCFar.off = va_arg(va, uint32_t); break; case DBGCVAR_TYPE_GC_PHYS: ExpectedArg.u.GCPhys = va_arg(va, RTGCPHYS); break; case DBGCVAR_TYPE_HC_FLAT: ExpectedArg.u.pvHCFlat = va_arg(va, void *); break; case DBGCVAR_TYPE_HC_PHYS: ExpectedArg.u.HCPhys = va_arg(va, RTHCPHYS); break; case DBGCVAR_TYPE_NUMBER: ExpectedArg.u.u64Number = va_arg(va, uint64_t); break; case DBGCVAR_TYPE_STRING: ExpectedArg.u.pszString = va_arg(va, const char *); break; case DBGCVAR_TYPE_SYMBOL: ExpectedArg.u.pszString = va_arg(va, const char *); break; default: RTTestFailed(g_hTest, "enmType=%u iArg=%u\n", ExpectedArg.enmType, iArg); ExpectedArg.u.u64Number = 0; break; } ExpectedArg.enmRangeType = (DBGCVARRANGETYPE)va_arg(va, int /*DBGCVARRANGETYPE*/); switch (ExpectedArg.enmRangeType) { case DBGCVAR_RANGE_NONE: ExpectedArg.u64Range = 0; break; case DBGCVAR_RANGE_ELEMENTS: ExpectedArg.u64Range = va_arg(va, uint64_t); break; case DBGCVAR_RANGE_BYTES: ExpectedArg.u64Range = va_arg(va, uint64_t); break; default: RTTestFailed(g_hTest, "enmRangeType=%u iArg=%u\n", ExpectedArg.enmRangeType, iArg); ExpectedArg.u64Range = 0; break; } if (!DBGCVarAreIdentical(&ExpectedArg, &paArgs[iArg])) RTTestFailed(g_hTest, "Arg #%u\n" "actual: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n" "expected: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n", iArg, paArgs[iArg].enmType, paArgs[iArg].u.u64Number, paArgs[iArg].enmRangeType, paArgs[iArg].u64Range, ExpectedArg.enmType, ExpectedArg.u.u64Number, ExpectedArg.enmRangeType, ExpectedArg.u64Range); } }
/** * Receive thread. * This is reading stuff from the network. */ DECLCALLBACK(int) ReceiveThread(RTTHREAD Thread, void *pvArg) { uint32_t cbReceived = 0; uint32_t cLostFrames = 0; uint32_t iFrame = UINT32_MAX; PMYARGS pArgs = (PMYARGS)pvArg; for (;;) { /* * Read data. */ while (IntNetRingHasMoreToRead(&pArgs->pBuf->Recv)) { uint8_t abBuf[16384 + 1024]; MYFRAMEHDR *pHdr = (MYFRAMEHDR *)&abBuf[0]; uint32_t cb = IntNetRingReadAndSkipFrame(&pArgs->pBuf->Recv, abBuf); /* check for termination frame. */ if ( pHdr->iFrame == 0xffffdead && pHdr->auEos[0] == 0xffffdead && pHdr->auEos[1] == 0xffffdead && pHdr->auEos[2] == 0xffffdead) { pArgs->u64End = RTTimeNanoTS(); RTThreadSleep(10); RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "receiver thread %.6Rhxs terminating.\n" " iFrame=%u cb=%'u c=%'u %'uKB/s %'ufps cLost=%'u \n", &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, (unsigned)(cbReceived * 1000000000.0 / 1024 / (pArgs->u64End - pArgs->u64Start)), (unsigned)((iFrame - cLostFrames) * 1000000000.0 / (pArgs->u64End - pArgs->u64Start)), cLostFrames); return VINF_SUCCESS; } /* validate frame header */ if ( pHdr->DstMac.au16[0] != pArgs->Mac.au16[0] || pHdr->DstMac.au16[1] != pArgs->Mac.au16[1] || pHdr->DstMac.au16[2] != pArgs->Mac.au16[2] || pHdr->SrcMac.au16[0] != pArgs->Mac.au16[0] || pHdr->SrcMac.au16[1] != pArgs->Mac.au16[1] || pHdr->SrcMac.au16[2] != (pArgs->Mac.au16[2] + 1) % 2) { RTTestFailed(g_hTest, "receiver thread %.6Rhxs received frame header: %.16Rhxs\n", &pArgs->Mac, abBuf); } /* frame stuff and stats. */ int32_t off = pHdr->iFrame - (iFrame + 1); if (off) { if (off > 0) { #ifndef IGNORE_LOST_FRAMES RTTestFailed(g_hTest, "receiver thread %.6Rhxs: iFrame=%#x *puFrame=%#x off=%d\n", &pArgs->Mac, iFrame, pHdr->iFrame, off); #endif cLostFrames += off; } else { cLostFrames++; RTTestFailed(g_hTest, "receiver thread %.6Rhxs: iFrame=%#x *puFrame=%#x off=%d\n", &pArgs->Mac, iFrame, pHdr->iFrame, off); } } iFrame = pHdr->iFrame; cbReceived += cb; } /* * Wait for data. */ int rc = IntNetR0IfWait(pArgs->hIf, g_pSession, RT_INDEFINITE_WAIT); switch (rc) { case VERR_INTERRUPTED: case VINF_SUCCESS: break; case VERR_SEM_DESTROYED: RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "receiver thread %.6Rhxs terminating. iFrame=%u cb=%'u c=%'u cLost=%'u\n", &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames); return VINF_SUCCESS; default: RTTestFailed(g_hTest, "receiver thread %.6Rhxs got odd return value %Rrc! iFrame=%u cb=%'u c=%'u cLost=%'u\n", &pArgs->Mac, rc, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames); return rc; } } }
int main(int argc, char **argv) { RTEXITCODE rcExit = RTTestInitAndCreate("tstRTPrfIO", &g_hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; RTTestBanner(g_hTest); /* * Parse arguments */ static const RTGETOPTDEF s_aOptions[] = { { "--test-dir", 'd', RTGETOPT_REQ_STRING }, }; bool fFileOpenCloseTest = true; bool fFileWriteByteTest = true; bool fPathQueryInfoTest = true; //bool fFileTests = true; //bool fDirTests = true; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 'd': g_pszTestDir = ValueUnion.psz; break; case 'V': RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "$Revision$\n"); return RTTestSummaryAndDestroy(g_hTest); case 'h': RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "usage: testname [-d <testdir>]\n"); return RTTestSummaryAndDestroy(g_hTest); default: RTTestFailed(g_hTest, "invalid argument"); RTGetOptPrintError(ch, &ValueUnion); return RTTestSummaryAndDestroy(g_hTest); } } /* * Set up and check the prerequisites. */ RTTESTI_CHECK_RC(RTPathJoin(g_szTestFile1, sizeof(g_szTestFile1), g_pszTestDir, "tstRTPrfIO-TestFile1"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPathJoin(g_szTestDir1, sizeof(g_szTestDir1), g_pszTestDir, "tstRTPrfIO-TestDir1"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPathJoin(g_szNotExitingFile, sizeof(g_szNotExitingFile), g_pszTestDir, "tstRTPrfIO-nonexistent-file"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPathJoin(g_szNotExitingDir, sizeof(g_szNotExitingDir), g_pszTestDir, "tstRTPrfIO-nonexistent-dir"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPathJoin(g_szNotExitingDirFile, sizeof(g_szNotExitingDirFile), g_szNotExitingDir, "nonexistent-file"), VINF_SUCCESS); RTTESTI_CHECK(RTDirExists(g_pszTestDir)); if (RTPathExists(g_szTestDir1)) RTTestFailed(g_hTest, "The primary test directory (%s) already exist, please remove it", g_szTestDir1); if (RTPathExists(g_szTestFile1)) RTTestFailed(g_hTest, "The primary test file (%s) already exist, please remove it", g_szTestFile1); if (RTPathExists(g_szNotExitingFile)) RTTestFailed(g_hTest, "'%s' exists, remove it", g_szNotExitingFile); if (RTPathExists(g_szNotExitingDir)) RTTestFailed(g_hTest, "'%s' exists, remove it", g_szNotExitingDir); if (RTPathExists(g_szNotExitingDirFile)) RTTestFailed(g_hTest, "'%s' exists, remove it", g_szNotExitingDirFile); /* * Do the testing. */ if (RTTestIErrorCount() == 0) { #if 1 if (fPathQueryInfoTest) benchmarkPathQueryInfo(); if (fFileOpenCloseTest) benchmarkFileOpenClose(); #endif if (fFileWriteByteTest) benchmarkFileWriteByte(); //if (fFileTests) // benchmarkFile(); //if (fDirTests) // benchmarkDir(); /* * Cleanup. */ RTFileDelete(g_szTestFile1); RTDirRemoveRecursive(g_szTestDir1, 0); RTTESTI_CHECK(RTDirExists(g_pszTestDir)); RTTESTI_CHECK(!RTPathExists(g_szTestDir1)); RTTESTI_CHECK(!RTPathExists(g_szTestFile1)); } return RTTestSummaryAndDestroy(g_hTest); }
static int mainChild(void) { /* * Init. */ int rc = RTR3InitExeNoArguments(RTR3INIT_FLAGS_SUPLIB); if (RT_FAILURE(rc)) { RTPrintf("tstSupSem-Zombie-Child: fatal error: RTR3InitExeNoArguments failed with rc=%Rrc\n", rc); return 1; } RTTEST hTest; rc = RTTestCreate("tstSupSem-Zombie-Child", &hTest); if (RT_FAILURE(rc)) { RTPrintf("tstSupSem-Zombie-Child: fatal error: RTTestCreate failed with rc=%Rrc\n", rc); return 1; } g_hTest = hTest; PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } g_pSession = pSession; /* * A semaphore of each kind and throw a bunch of threads on them. */ SUPSEMEVENT hEvent = NIL_SUPSEMEVENT; RTTESTI_CHECK_RC(rc = SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); if (RT_SUCCESS(rc)) { SUPSEMEVENTMULTI hEventMulti = NIL_SUPSEMEVENT; RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS); if (RT_SUCCESS(rc)) { for (uint32_t cThreads = 0; cThreads < 5; cThreads++) { RTTHREAD hThread; RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemSRETimed, (void *)hEvent, 0, RTTHREADTYPE_TIMER, 0 /*fFlags*/, "IntSRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemMRETimed, (void *)hEventMulti, 0, RTTHREADTYPE_TIMER, 0 /*fFlags*/, "IntMRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemSREInf, (void *)hEvent, 0, RTTHREADTYPE_TIMER, 0 /*fFlags*/, "IntSRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemMREInf, (void *)hEventMulti, 0, RTTHREADTYPE_TIMER, 0 /*fFlags*/, "IntMRE"), VINF_SUCCESS); RTThreadSleep(2); } RTThreadSleep(50); /* * This is where the test really starts... */ return 0; } } return RTTestSummaryAndDestroy(hTest); }
static DECLCALLBACK(int) Test4Thread(RTTHREAD ThreadSelf, void *pvUser) { /* Use randomization to get a little more variation of the sync pattern. We use a pseudo random generator here so that we don't end up testing the speed of the /dev/urandom implementation, but rather the read-write semaphores. */ int rc; RTRAND hRand; RTTEST_CHECK_RC_OK_RET(g_hTest, rc = RTRandAdvCreateParkMiller(&hRand), rc); RTTEST_CHECK_RC_OK_RET(g_hTest, rc = RTRandAdvSeed(hRand, (uintptr_t)ThreadSelf), rc); unsigned c100 = RTRandAdvU32Ex(hRand, 0, 99); uint64_t *pcItr = (uint64_t *)pvUser; bool fWrite; for (;;) { unsigned readrec = RTRandAdvU32Ex(hRand, 0, 3); unsigned writerec = RTRandAdvU32Ex(hRand, 0, 3); /* Don't overdo recursion testing. */ if (readrec > 1) readrec--; if (writerec > 1) writerec--; fWrite = (c100 < g_uWritePercent); if (fWrite) { for (unsigned i = 0; i <= writerec; i++) { rc = RTCritSectRwEnterExcl(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Write recursion %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } if (RT_FAILURE(rc)) break; if (ASMAtomicIncU32(&g_cConcurrentWriters) != 1) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s after write locking it", g_cConcurrentWriters, RTThreadSelfName()); break; } if (g_cConcurrentReaders != 0) { RTTestFailed(g_hTest, "g_cConcurrentReaders=%u on %s after write locking it", g_cConcurrentReaders, RTThreadSelfName()); break; } } else { rc = RTCritSectRwEnterShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read locking on %s failed with rc=%Rrc", RTThreadSelfName(), rc); break; } ASMAtomicIncU32(&g_cConcurrentReaders); if (g_cConcurrentWriters != 0) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s after read locking it", g_cConcurrentWriters, RTThreadSelfName()); break; } } for (unsigned i = 0; i < readrec; i++) { rc = RTCritSectRwEnterShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read recursion %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } if (RT_FAILURE(rc)) break; /* * Check for fairness: The values of the threads should not differ too much */ (*pcItr)++; /* * Check for correctness: Give other threads a chance. If the implementation is * correct, no other thread will be able to enter this lock now. */ if (g_fYield) RTThreadYield(); for (unsigned i = 0; i < readrec; i++) { rc = RTCritSectRwLeaveShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read release %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } if (RT_FAILURE(rc)) break; if (fWrite) { if (ASMAtomicDecU32(&g_cConcurrentWriters) != 0) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s before write release", g_cConcurrentWriters, RTThreadSelfName()); break; } if (g_cConcurrentReaders != 0) { RTTestFailed(g_hTest, "g_cConcurrentReaders=%u on %s before write release", g_cConcurrentReaders, RTThreadSelfName()); break; } for (unsigned i = 0; i <= writerec; i++) { rc = RTCritSectRwLeaveExcl(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Write release %u on %s failed with rc=%Rrc", i, RTThreadSelfName(), rc); break; } } } else { if (g_cConcurrentWriters != 0) { RTTestFailed(g_hTest, "g_cConcurrentWriters=%u on %s before read release", g_cConcurrentWriters, RTThreadSelfName()); break; } ASMAtomicDecU32(&g_cConcurrentReaders); rc = RTCritSectRwLeaveShared(&g_CritSectRw); if (RT_FAILURE(rc)) { RTTestFailed(g_hTest, "Read release on %s failed with rc=%Rrc", RTThreadSelfName(), rc); break; } } if (g_fTerminate) break; c100++; c100 %= 100; } if (!g_fQuiet) RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Thread %s exited with %lld\n", RTThreadSelfName(), *pcItr); RTRandAdvDestroy(hRand); return VINF_SUCCESS; }
int main(int argc, char **argv) { bool fSys = true; bool fGip = false; #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) fGip = true; #endif /* * Init. */ int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); if (argc == 2 && !strcmp(argv[1], "child")) { RTThreadSleep(300); return 0; } RTTEST hTest; rc = RTTestCreate("tstSupSem", &hTest); if (RT_FAILURE(rc)) { RTPrintf("tstSupSem: fatal error: RTTestCreate failed with rc=%Rrc\n", rc); return 1; } g_hTest = hTest; PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } g_pSession = pSession; RTTestBanner(hTest); /* * Basic API checks. */ RTTestSub(hTest, "Single Release Event (SRE) API"); SUPSEMEVENT hEvent = NIL_SUPSEMEVENT; RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 20), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,1000),VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(SUPSemEventClose(pSession, NIL_SUPSEMEVENT), VINF_SUCCESS); RTTestSub(hTest, "Multiple Release Event (MRE) API"); SUPSEMEVENTMULTI hEventMulti = NIL_SUPSEMEVENT; RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,1000), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiReset(pSession, hEventMulti), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20), VERR_TIMEOUT); RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 20), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,1000), VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VINF_OBJECT_DESTROYED); RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, NIL_SUPSEMEVENTMULTI), VINF_SUCCESS); #if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) RTTestSub(hTest, "SRE Interruptibility"); RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); g_cMillies = RT_INDEFINITE_WAIT; RTTHREAD hThread = NIL_RTTHREAD; RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleSRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS); RTThreadSleep(120); RTThreadPoke(hThread); int rcThread = VINF_SUCCESS; RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED); RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); g_cMillies = 120*1000; hThread = NIL_RTTHREAD; RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleSRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS); RTThreadSleep(120); RTThreadPoke(hThread); rcThread = VINF_SUCCESS; RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED); RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestSub(hTest, "MRE Interruptibility"); RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS); g_cMillies = RT_INDEFINITE_WAIT; hThread = NIL_RTTHREAD; RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleMRE, (void *)hEventMulti, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntMRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS); RTThreadSleep(120); RTThreadPoke(hThread); rcThread = VINF_SUCCESS; RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED); RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VINF_OBJECT_DESTROYED); RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti), VINF_SUCCESS); g_cMillies = 120*1000; hThread = NIL_RTTHREAD; RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleMRE, (void *)hEventMulti, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntMRE"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadUserWait(hThread, 60*1000), VINF_SUCCESS); RTThreadSleep(120); RTThreadPoke(hThread); rcThread = VINF_SUCCESS; RTTESTI_CHECK_RC(RTThreadWait(hThread, 60*1000, &rcThread), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread, VERR_INTERRUPTED); RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti), VINF_OBJECT_DESTROYED); /* * Fork test. * Spawn a thread waiting for an event, then spawn a new child process (of * ourselves) and make sure that this does not alter the intended behaviour * of our event semaphore implementation (see @bugref{5090}). */ RTTestSub(hTest, "SRE Process Spawn"); hThread = NIL_RTTHREAD; g_cMillies = 120*1000; RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleSRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS); const char *apszArgs[3] = { argv[0], "child", NULL }; RTPROCESS Process = NIL_RTPROCESS; RTThreadSleep(250); RTTESTI_CHECK_RC(RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0, &Process), VINF_SUCCESS); RTThreadSleep(250); RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent), VINF_SUCCESS); rcThread = VERR_GENERAL_FAILURE; RTTESTI_CHECK_RC(RTThreadWait(hThread, 120*1000, &rcThread), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread, VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestSub(hTest, "MRE Process Spawn"); hThread = NIL_RTTHREAD; g_cMillies = 120*1000; RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadCreate(&hThread, tstSupSemInterruptibleMRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS); RTTHREAD hThread2 = NIL_RTTHREAD; RTTESTI_CHECK_RC(RTThreadCreate(&hThread2, tstSupSemInterruptibleMRE, (void *)hEvent, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "IntSRE"), VINF_SUCCESS); Process = NIL_RTPROCESS; RTThreadSleep(250); RTTESTI_CHECK_RC(RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0, &Process), VINF_SUCCESS); RTThreadSleep(250); RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEvent), VINF_SUCCESS); rcThread = VERR_GENERAL_FAILURE; RTTESTI_CHECK_RC(RTThreadWait(hThread, 120*1000, &rcThread), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread, VINF_SUCCESS); int rcThread2 = VERR_GENERAL_FAILURE; RTTESTI_CHECK_RC(RTThreadWait(hThread2, 120*1000, &rcThread2), VINF_SUCCESS); RTTESTI_CHECK_RC(rcThread2, VINF_SUCCESS); RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED); #endif /* !OS2 && !WINDOWS */ { #define LOOP_COUNT 20 static unsigned const s_acMsIntervals[] = { 0, 1, 2, 3, 4, 8, 10, 16, 32 }; if (RTTestErrorCount(hTest) == 0) { RTTestSub(hTest, "SRE Timeout Accuracy (ms)"); RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); uint32_t cInterrupted = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++) { uint64_t cMs = s_acMsIntervals[i]; uint64_t cNsMinSys = UINT64_MAX; uint64_t cNsMin = UINT64_MAX; uint64_t cNsTotalSys= 0; uint64_t cNsTotal = 0; unsigned cLoops = 0; while (cLoops < LOOP_COUNT) { uint64_t u64StartSys = RTTimeSystemNanoTS(); uint64_t u64Start = RTTimeNanoTS(); int rcX = SUPSemEventWaitNoResume(pSession, hEvent, cMs); uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys; uint64_t cNsElapsed = RTTimeNanoTS() - u64Start; if (rcX == VERR_INTERRUPTED) { cInterrupted++; continue; /* retry */ } if (rcX != VERR_TIMEOUT) RTTestFailed(hTest, "%Rrc cLoops=%u cMs=%u", rcX, cLoops, cMs); if (cNsElapsedSys < cNsMinSys) cNsMinSys = cNsElapsedSys; if (cNsElapsed < cNsMin) cNsMin = cNsElapsed; cNsTotalSys += cNsElapsedSys; cNsTotal += cNsElapsed; cLoops++; } if (fSys) { RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%u ms min (clock=sys)", cMs); RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=sys)", cMs); } if (fGip) { RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%u ms min (clock=gip)", cMs); RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=gip)", cMs); } } RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned"); } if (RTTestErrorCount(hTest) == 0) { RTTestSub(hTest, "MRE Timeout Accuracy (ms)"); RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS); uint32_t cInterrupted = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++) { uint64_t cMs = s_acMsIntervals[i]; uint64_t cNsMinSys = UINT64_MAX; uint64_t cNsMin = UINT64_MAX; uint64_t cNsTotalSys= 0; uint64_t cNsTotal = 0; unsigned cLoops = 0; while (cLoops < LOOP_COUNT) { uint64_t u64StartSys = RTTimeSystemNanoTS(); uint64_t u64Start = RTTimeNanoTS(); int rcX = SUPSemEventMultiWaitNoResume(pSession, hEvent, cMs); uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys; uint64_t cNsElapsed = RTTimeNanoTS() - u64Start; if (rcX == VERR_INTERRUPTED) { cInterrupted++; continue; /* retry */ } if (rcX != VERR_TIMEOUT) RTTestFailed(hTest, "%Rrc cLoops=%u cMs=%u", rcX, cLoops, cMs); if (cNsElapsedSys < cNsMinSys) cNsMinSys = cNsElapsedSys; if (cNsElapsed < cNsMin) cNsMin = cNsElapsed; cNsTotalSys += cNsElapsedSys; cNsTotal += cNsElapsed; cLoops++; } if (fSys) { RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%u ms min (clock=sys)", cMs); RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=sys)", cMs); } if (fGip) { RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%u ms min (clock=gip)", cMs); RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%u ms avg (clock=gip)", cMs); } } RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned"); } } { static uint32_t const s_acNsIntervals[] = { 0, 1000, 5000, 15000, 30000, 50000, 100000, 250000, 500000, 750000, 900000, 1500000, 2200000 }; if (RTTestErrorCount(hTest) == 0) { RTTestSub(hTest, "SUPSemEventWaitNsRelIntr Accuracy"); RTTestValueF(hTest, SUPSemEventGetResolution(pSession), RTTESTUNIT_NS, "SRE resolution"); RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); uint32_t cInterrupted = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++) { uint64_t cNs = s_acNsIntervals[i]; uint64_t cNsMinSys = UINT64_MAX; uint64_t cNsMin = UINT64_MAX; uint64_t cNsTotalSys= 0; uint64_t cNsTotal = 0; unsigned cLoops = 0; while (cLoops < LOOP_COUNT) { uint64_t u64StartSys = RTTimeSystemNanoTS(); uint64_t u64Start = RTTimeNanoTS(); int rcX = SUPSemEventWaitNsRelIntr(pSession, hEvent, cNs); uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys; uint64_t cNsElapsed = RTTimeNanoTS() - u64Start; if (rcX == VERR_INTERRUPTED) { cInterrupted++; continue; /* retry */ } if (rcX != VERR_TIMEOUT) RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs); if (cNsElapsedSys < cNsMinSys) cNsMinSys = cNsElapsedSys; if (cNsElapsed < cNsMin) cNsMin = cNsElapsed; cNsTotalSys += cNsElapsedSys; cNsTotal += cNsElapsed; cLoops++; } if (fSys) { RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs); RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs); } if (fGip) { RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs); RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs); } } RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned"); } if (RTTestErrorCount(hTest) == 0) { RTTestSub(hTest, "SUPSemEventMultiWaitNsRelIntr Accuracy"); RTTestValueF(hTest, SUPSemEventMultiGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution"); RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS); uint32_t cInterrupted = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++) { uint64_t cNs = s_acNsIntervals[i]; uint64_t cNsMinSys = UINT64_MAX; uint64_t cNsMin = UINT64_MAX; uint64_t cNsTotalSys= 0; uint64_t cNsTotal = 0; unsigned cLoops = 0; while (cLoops < LOOP_COUNT) { uint64_t u64StartSys = RTTimeSystemNanoTS(); uint64_t u64Start = RTTimeNanoTS(); int rcX = SUPSemEventMultiWaitNsRelIntr(pSession, hEvent, cNs); uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys; uint64_t cNsElapsed = RTTimeNanoTS() - u64Start; if (rcX == VERR_INTERRUPTED) { cInterrupted++; continue; /* retry */ } if (rcX != VERR_TIMEOUT) RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs); if (cNsElapsedSys < cNsMinSys) cNsMinSys = cNsElapsedSys; if (cNsElapsed < cNsMin) cNsMin = cNsElapsed; cNsTotalSys += cNsElapsedSys; cNsTotal += cNsElapsed; cLoops++; } if (fSys) { RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs); RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs); } if (fGip) { RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs); RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs); } } RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned"); } if (RTTestErrorCount(hTest) == 0) { RTTestSub(hTest, "SUPSemEventWaitNsAbsIntr Accuracy"); RTTestValueF(hTest, SUPSemEventGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution"); RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS); uint32_t cInterrupted = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++) { uint64_t cNs = s_acNsIntervals[i]; uint64_t cNsMinSys = UINT64_MAX; uint64_t cNsMin = UINT64_MAX; uint64_t cNsTotalSys= 0; uint64_t cNsTotal = 0; unsigned cLoops = 0; while (cLoops < LOOP_COUNT) { uint64_t u64StartSys = RTTimeSystemNanoTS(); uint64_t u64Start = RTTimeNanoTS(); uint64_t uAbsDeadline = (fGip ? u64Start : u64StartSys) + cNs; int rcX = SUPSemEventWaitNsAbsIntr(pSession, hEvent, uAbsDeadline); uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys; uint64_t cNsElapsed = RTTimeNanoTS() - u64Start; if (rcX == VERR_INTERRUPTED) { cInterrupted++; continue; /* retry */ } if (rcX != VERR_TIMEOUT) RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs); if (cNsElapsedSys < cNsMinSys) cNsMinSys = cNsElapsedSys; if (cNsElapsed < cNsMin) cNsMin = cNsElapsed; cNsTotalSys += cNsElapsedSys; cNsTotal += cNsElapsed; cLoops++; } if (fSys) { RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs); RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs); } if (fGip) { RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs); RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs); } } RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned"); } if (RTTestErrorCount(hTest) == 0) { RTTestSub(hTest, "SUPSemEventMultiWaitNsAbsIntr Accuracy"); RTTestValueF(hTest, SUPSemEventMultiGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution"); RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS); uint32_t cInterrupted = 0; for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++) { uint64_t cNs = s_acNsIntervals[i]; uint64_t cNsMinSys = UINT64_MAX; uint64_t cNsMin = UINT64_MAX; uint64_t cNsTotalSys= 0; uint64_t cNsTotal = 0; unsigned cLoops = 0; while (cLoops < LOOP_COUNT) { uint64_t u64StartSys = RTTimeSystemNanoTS(); uint64_t u64Start = RTTimeNanoTS(); uint64_t uAbsDeadline = (fGip ? u64Start : u64StartSys) + cNs; int rcX = SUPSemEventMultiWaitNsAbsIntr(pSession, hEvent, uAbsDeadline); uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys; uint64_t cNsElapsed = RTTimeNanoTS() - u64Start; if (rcX == VERR_INTERRUPTED) { cInterrupted++; continue; /* retry */ } if (rcX != VERR_TIMEOUT) RTTestFailed(hTest, "%Rrc cLoops=%u cNs=%u", rcX, cLoops, cNs); if (cNsElapsedSys < cNsMinSys) cNsMinSys = cNsElapsedSys; if (cNsElapsed < cNsMin) cNsMin = cNsElapsed; cNsTotalSys += cNsElapsedSys; cNsTotal += cNsElapsed; cLoops++; } if (fSys) { RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%'u ns min (clock=sys)", cNs); RTTestValueF(hTest, cNsTotalSys / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs); } if (fGip) { RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%'u ns min (clock=gip)", cNs); RTTestValueF(hTest, cNsTotal / cLoops, RTTESTUNIT_NS, "%'u ns avg (clock=gip)", cNs); } } RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED); RTTestValueF(hTest, cInterrupted, RTTESTUNIT_OCCURRENCES, "VERR_INTERRUPTED returned"); } } /* * Done. */ return RTTestSummaryAndDestroy(hTest); }
int main (int argc, char **argv) { #ifndef VBOX RTPrintf("tstSup: SKIPPED\n"); return 0; #else /* * Init. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTR0DbgKrnlInfo", &hTest); if (rc) return rc; RTTestBanner(hTest); uint8_t *pbPage = (uint8_t *)RTTestGuardedAllocTail(hTest, PAGE_SIZE); if (!pbPage) { RTTestFailed(hTest, "RTTestGuardedAllocTail failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } char szPath[RTPATH_MAX]; rc = RTPathExecDir(szPath, sizeof(szPath)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szPath, sizeof(szPath), "tstRTR0DbgKrnlInfo.r0"); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "Failed constructing .r0 filename (rc=%Rrc)", rc); return RTTestSummaryAndDestroy(hTest); } void *pvImageBase; rc = SUPR3LoadServiceModule(szPath, "tstRTR0DbgKrnlInfo", "TSTR0DbgKrnlInfoSrvReqHandler", &pvImageBase); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3LoadServiceModule(%s,,,) failed with rc=%Rrc\n", szPath, rc); return RTTestSummaryAndDestroy(hTest); } /* test request */ struct { SUPR0SERVICEREQHDR Hdr; char szMsg[256]; } Req; /* * Sanity checks. */ RTTestSub(hTest, "Sanity"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstRTR0DbgKrnlInfo", sizeof("tstRTR0DbgKrnlInfo") - 1, TSTRTR0DBGKRNLINFO_SANITY_OK, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(Req.szMsg[0] == '\0', ("%s", Req.szMsg)); if (Req.szMsg[0] != '\0') return RTTestSummaryAndDestroy(hTest); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstRTR0DbgKrnlInfo", sizeof("tstRTR0DbgKrnlInfo") - 1, TSTRTR0DBGKRNLINFO_SANITY_FAILURE, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(!strncmp(Req.szMsg, RT_STR_TUPLE("!42failure42")), ("%s", Req.szMsg)); if (strncmp(Req.szMsg, RT_STR_TUPLE("!42failure42"))) return RTTestSummaryAndDestroy(hTest); /* * Basic tests, bail out on failure. */ RTTestSub(hTest, "Basics"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstRTR0DbgKrnlInfo", sizeof("tstRTR0DbgKrnlInfo") - 1, TSTRTR0DBGKRNLINFO_BASIC, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); if (Req.szMsg[0] == '!') { RTTestIFailed("%s", &Req.szMsg[1]); return RTTestSummaryAndDestroy(hTest); } if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); /* * Done. */ return RTTestSummaryAndDestroy(hTest); #endif }
int main(int argc, char **argv) { RTTEST hTest; RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, 0 /*fRtInit*/, "tstSupTscDelta", &hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; /* * Parse args */ static const RTGETOPTDEF g_aOptions[] = { { "--iterations", 'i', RTGETOPT_REQ_INT32 }, { "--delay", 'd', RTGETOPT_REQ_INT32 }, }; uint32_t cIterations = 0; /* Currently 0 so that it doesn't upset testing. */ uint32_t cMsSleepBetweenIterations = 10; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 'd': cMsSleepBetweenIterations = ValueUnion.u32; break; case 'i': cIterations = ValueUnion.u32; break; default: return RTGetOptPrintError(ch, &ValueUnion); } } if (!cIterations) return RTTestSkipAndDestroy(hTest, "Nothing to do. The --iterations argument is 0 or not given."); /* * Init */ PSUPDRVSESSION pSession = NIL_RTR0PTR; int rc = SUPR3Init(&pSession); if (RT_SUCCESS(rc)) { PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; if (pGip) { if (pGip->enmUseTscDelta < SUPGIPUSETSCDELTA_PRACTICALLY_ZERO) return RTTestSkipAndDestroy(hTest, "No deltas to play with: enmUseTscDelta=%d\n", pGip->enmUseTscDelta); /* * Init stats. */ struct { int64_t iLowest; int64_t iHighest; int64_t iTotal; uint64_t uAbsMin; uint64_t uAbsMax; uint64_t uAbsTotal; } aCpuStats[RTCPUSET_MAX_CPUS]; RT_ZERO(aCpuStats); for (uint32_t i = 0; i < pGip->cCpus; i++) { aCpuStats[i].iLowest = INT64_MAX; aCpuStats[i].iHighest = INT64_MIN; aCpuStats[i].uAbsMin = UINT64_MAX; } /* * Do the work. */ for (uint32_t iIteration = 0; ; iIteration++) { /* * Display the current deltas and gather statistics. */ RTPrintf("tstSupTscDelta: Iteration #%u results:", iIteration); for (uint32_t iCpu = 0; iCpu < pGip->cCpus; iCpu++) { int64_t iTscDelta = pGip->aCPUs[iCpu].i64TSCDelta; /* print */ if ((iCpu % 4) == 0) RTPrintf("\ntstSupTscDelta:"); if (pGip->aCPUs[iCpu].enmState != SUPGIPCPUSTATE_ONLINE) RTPrintf(" %02x: offline ", iCpu); else if (iTscDelta != INT64_MAX) RTPrintf(" %02x: %-12lld", iCpu, iTscDelta); else RTPrintf(" %02x: INT64_MAX ", iCpu); /* stats */ if ( iTscDelta != INT64_MAX && pGip->aCPUs[iCpu].enmState == SUPGIPCPUSTATE_ONLINE) { if (aCpuStats[iCpu].iLowest > iTscDelta) aCpuStats[iCpu].iLowest = iTscDelta; if (aCpuStats[iCpu].iHighest < iTscDelta) aCpuStats[iCpu].iHighest = iTscDelta; aCpuStats[iCpu].iTotal += iTscDelta; uint64_t uAbsTscDelta = iTscDelta >= 0 ? (uint64_t)iTscDelta : (uint64_t)-iTscDelta; if (aCpuStats[iCpu].uAbsMin > uAbsTscDelta) aCpuStats[iCpu].uAbsMin = uAbsTscDelta; if (aCpuStats[iCpu].uAbsMax < uAbsTscDelta) aCpuStats[iCpu].uAbsMax = uAbsTscDelta; aCpuStats[iCpu].uAbsTotal += uAbsTscDelta; } } if (((pGip->cCpus - 1) % 4) != 0) RTPrintf("\n"); /* * Done? */ if (iIteration + 1 >= cIterations) break; /* * Force a new measurement. */ RTThreadSleep(cMsSleepBetweenIterations); for (uint32_t iCpu = 0; iCpu < pGip->cCpus; iCpu++) if (pGip->aCPUs[iCpu].enmState == SUPGIPCPUSTATE_ONLINE) { rc = SUPR3TscDeltaMeasure(pGip->aCPUs[iCpu].idCpu, false /*fAsync*/, true /*fForce*/, 64, 16 /*ms*/); if (RT_FAILURE(rc)) RTTestFailed(hTest, "SUPR3TscDeltaMeasure failed on %#x: %Rrc", pGip->aCPUs[iCpu].idCpu, rc); } } /* * Display statistics that we've gathered. */ RTPrintf("tstSupTscDelta: Results:\n"); int64_t iLowest = INT64_MAX; int64_t iHighest = INT64_MIN; int64_t iTotal = 0; uint32_t cTotal = 0; for (uint32_t iCpu = 0; iCpu < pGip->cCpus; iCpu++) { if (pGip->aCPUs[iCpu].enmState != SUPGIPCPUSTATE_ONLINE) RTPrintf("tstSupTscDelta: %02x: offline\n", iCpu); else { RTPrintf("tstSupTscDelta: %02x: lowest=%-12lld highest=%-12lld average=%-12lld spread=%-12lld\n", iCpu, aCpuStats[iCpu].iLowest, aCpuStats[iCpu].iHighest, aCpuStats[iCpu].iTotal / cIterations, aCpuStats[iCpu].iHighest - aCpuStats[iCpu].iLowest); RTPrintf( "tstSupTscDelta: absmin=%-12llu absmax=%-12llu absavg=%-12llu idCpu=%#4x idApic=%#4x\n", aCpuStats[iCpu].uAbsMin, aCpuStats[iCpu].uAbsMax, aCpuStats[iCpu].uAbsTotal / cIterations, pGip->aCPUs[iCpu].idCpu, pGip->aCPUs[iCpu].idApic); if (iLowest > aCpuStats[iCpu].iLowest) iLowest = aCpuStats[iCpu].iLowest; if (iHighest < aCpuStats[iCpu].iHighest) iHighest = aCpuStats[iCpu].iHighest; iTotal += aCpuStats[iCpu].iHighest; cTotal += cIterations; } } RTPrintf("tstSupTscDelta: all: lowest=%-12lld highest=%-12lld average=%-12lld spread=%-12lld\n", iLowest, iHighest, iTotal / cTotal, iHighest - iLowest); } else RTTestFailed(hTest, "g_pSUPGlobalInfoPage is NULL"); SUPR3Term(false /*fForced*/); } else RTTestFailed(hTest, "SUPR3Init failed: %Rrc", rc); return RTTestSummaryAndDestroy(hTest); }
int main() { /* * Init. */ RTTEST hTest; RTEXITCODE rcExit = RTTestInitExAndCreate(0, NULL, RTR3INIT_FLAGS_SUPLIB, "tstRTTime", &hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; RTTestBanner(hTest); /* * RTNanoTimeTS() shall never return something which * is less or equal to the return of the previous call. */ RTTimeSystemNanoTS(); RTTimeNanoTS(); RTThreadYield(); uint64_t u64RTStartTS = RTTimeNanoTS(); uint64_t u64OSStartTS = RTTimeSystemNanoTS(); uint32_t i; uint64_t u64Prev = RTTimeNanoTS(); for (i = 0; i < 100*_1M; i++) { uint64_t u64 = RTTimeNanoTS(); if (u64 <= u64Prev) { /** @todo wrapping detection. */ RTTestFailed(hTest, "i=%#010x u64=%#llx u64Prev=%#llx (1)\n", i, u64, u64Prev); if (RTTestErrorCount(hTest) >= 256) break; RTThreadYield(); u64 = RTTimeNanoTS(); } else if (u64 - u64Prev > 1000000000 /* 1sec */) { RTTestFailed(hTest, "i=%#010x u64=%#llx u64Prev=%#llx delta=%lld\n", i, u64, u64Prev, u64 - u64Prev); if (RTTestErrorCount(hTest) >= 256) break; RTThreadYield(); u64 = RTTimeNanoTS(); } if (!(i & (_1M*2 - 1))) { RTTestPrintf(hTest, RTTESTLVL_INFO, "i=%#010x u64=%#llx u64Prev=%#llx delta=%lld\n", i, u64, u64Prev, u64 - u64Prev); RTThreadYield(); u64 = RTTimeNanoTS(); } u64Prev = u64; } RTTimeSystemNanoTS(); RTTimeNanoTS(); RTThreadYield(); uint64_t u64RTElapsedTS = RTTimeNanoTS(); uint64_t u64OSElapsedTS = RTTimeSystemNanoTS(); u64RTElapsedTS -= u64RTStartTS; u64OSElapsedTS -= u64OSStartTS; int64_t i64Diff = u64OSElapsedTS >= u64RTElapsedTS ? u64OSElapsedTS - u64RTElapsedTS : u64RTElapsedTS - u64OSElapsedTS; if (i64Diff > (int64_t)(u64OSElapsedTS / 1000)) RTTestFailed(hTest, "total time differs too much! u64OSElapsedTS=%#llx u64RTElapsedTS=%#llx delta=%lld\n", u64OSElapsedTS, u64RTElapsedTS, u64OSElapsedTS - u64RTElapsedTS); else { if (u64OSElapsedTS >= u64RTElapsedTS) RTTestValue(hTest, "Total time delta", u64OSElapsedTS - u64RTElapsedTS, RTTESTUNIT_NS); else RTTestValue(hTest, "Total time delta", u64RTElapsedTS - u64OSElapsedTS, RTTESTUNIT_NS); RTTestPrintf(hTest, RTTESTLVL_INFO, "total time difference: u64OSElapsedTS=%#llx u64RTElapsedTS=%#llx delta=%lld\n", u64OSElapsedTS, u64RTElapsedTS, u64OSElapsedTS - u64RTElapsedTS); } #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) /** @todo This isn't really x86 or AMD64 specific... */ RTTestValue(hTest, "RTTimeDbgSteps", RTTimeDbgSteps(), RTTESTUNIT_OCCURRENCES); RTTestValue(hTest, "RTTimeDbgSteps pp", ((uint64_t)RTTimeDbgSteps() * 1000) / i, RTTESTUNIT_PP1K); RTTestValue(hTest, "RTTimeDbgExpired", RTTimeDbgExpired(), RTTESTUNIT_OCCURRENCES); RTTestValue(hTest, "RTTimeDbgExpired pp", ((uint64_t)RTTimeDbgExpired() * 1000) / i, RTTESTUNIT_PP1K); RTTestValue(hTest, "RTTimeDbgBad", RTTimeDbgBad(), RTTESTUNIT_OCCURRENCES); RTTestValue(hTest, "RTTimeDbgBad pp", ((uint64_t)RTTimeDbgBad() * 1000) / i, RTTESTUNIT_PP1K); RTTestValue(hTest, "RTTimeDbgRaces", RTTimeDbgRaces(), RTTESTUNIT_OCCURRENCES); RTTestValue(hTest, "RTTimeDbgRaces pp", ((uint64_t)RTTimeDbgRaces() * 1000) / i, RTTESTUNIT_PP1K); #endif return RTTestSummaryAndDestroy(hTest); }
/** * Entry point. */ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) { RT_NOREF1(envp); /* * Init runtime and the test environment. */ RTTEST hTest; RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, RTR3INIT_FLAGS_SUPLIB, "tstVMM", &hTest); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; /* * Parse arguments. */ static const RTGETOPTDEF s_aOptions[] = { { "--cpus", 'c', RTGETOPT_REQ_UINT8 }, { "--test", 't', RTGETOPT_REQ_STRING }, { "--stat", 's', RTGETOPT_REQ_NOTHING }, }; enum { kTstVMMTest_VMM, kTstVMMTest_TM, kTstVMMTest_MSRs, kTstVMMTest_KnownMSRs, kTstVMMTest_MSRExperiments } enmTestOpt = kTstVMMTest_VMM; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 'c': g_cCpus = ValueUnion.u8; break; case 't': if (!strcmp("vmm", ValueUnion.psz)) enmTestOpt = kTstVMMTest_VMM; else if (!strcmp("tm", ValueUnion.psz)) enmTestOpt = kTstVMMTest_TM; else if (!strcmp("msr", ValueUnion.psz) || !strcmp("msrs", ValueUnion.psz)) enmTestOpt = kTstVMMTest_MSRs; else if (!strcmp("known-msr", ValueUnion.psz) || !strcmp("known-msrs", ValueUnion.psz)) enmTestOpt = kTstVMMTest_KnownMSRs; else if (!strcmp("msr-experiments", ValueUnion.psz)) enmTestOpt = kTstVMMTest_MSRExperiments; else { RTPrintf("tstVMM: unknown test: '%s'\n", ValueUnion.psz); return 1; } break; case 's': g_fStat = true; break; case 'h': RTPrintf("usage: tstVMM [--cpus|-c cpus] [-s] [--test <vmm|tm|msrs|known-msrs>]\n"); return 1; case 'V': RTPrintf("$Revision$\n"); return 0; default: return RTGetOptPrintError(ch, &ValueUnion); } } /* * Create the test VM. */ RTPrintf(TESTCASE ": Initializing...\n"); PVM pVM; PUVM pUVM; int rc = VMR3Create(g_cCpus, NULL, NULL, NULL, tstVMMConfigConstructor, NULL, &pVM, &pUVM); if (RT_SUCCESS(rc)) { PDMR3LdrEnumModules(pVM, tstVMMLdrEnum, NULL); RTStrmFlush(g_pStdOut); RTThreadSleep(256); /* * Do the requested testing. */ switch (enmTestOpt) { case kTstVMMTest_VMM: { RTTestSub(hTest, "VMM"); rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc); if (g_fStat) STAMR3Dump(pUVM, "*"); break; } case kTstVMMTest_TM: { RTTestSub(hTest, "TM"); for (VMCPUID idCpu = 1; idCpu < g_cCpus; idCpu++) { rc = VMR3ReqCallNoWaitU(pUVM, idCpu, (PFNRT)tstTMWorker, 2, pVM, hTest); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMR3ReqCall failed: rc=%Rrc\n", rc); } rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)tstTMWorker, 2, pVM, hTest); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc); if (g_fStat) STAMR3Dump(pUVM, "*"); break; } case kTstVMMTest_MSRs: { RTTestSub(hTest, "MSRs"); if (g_cCpus == 1) { rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoBruteForceMsrs, 1, pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoBruteForceMsrs failed: rc=%Rrc\n", rc); } else RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n"); break; } case kTstVMMTest_KnownMSRs: { RTTestSub(hTest, "Known MSRs"); if (g_cCpus == 1) { rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoKnownMsrs, 1, pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoKnownMsrs failed: rc=%Rrc\n", rc); } else RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n"); break; } case kTstVMMTest_MSRExperiments: { RTTestSub(hTest, "MSR Experiments"); if (g_cCpus == 1) { rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoMsrExperiments, 1, pVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMMDoMsrExperiments failed: rc=%Rrc\n", rc); } else RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n"); break; } } /* * Cleanup. */ rc = VMR3PowerOff(pUVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMR3PowerOff failed: rc=%Rrc\n", rc); rc = VMR3Destroy(pUVM); if (RT_FAILURE(rc)) RTTestFailed(hTest, "VMR3Destroy failed: rc=%Rrc\n", rc); VMR3ReleaseUVM(pUVM); } else RTTestFailed(hTest, "VMR3Create failed: rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); }