/** * Basic API checks. */ static void tst1(void) { RTTestISub("Manifest creation"); size_t cbSize = 0; size_t iFailed = 0; /* * test1.txt = "This is a test text." * test2.txt = "Another test text." */ static RTMANIFESTTEST /*const*/ s_aFiles[] = /** @todo API misdesign, this should be const. */ { { "test1.txt", "794a8cc644b318ae6461aeea62915e399e441e8" }, { "test2.txt", "f17393902ee94c1e8bbd4bf417cdc70051feca00" } }; static const char s_szTestPattern[] = "SHA1 (test1.txt)= 794a8cc644b318ae6461aeea62915e399e441e8\n" "SHA1 (test2.txt)= f17393902ee94c1e8bbd4bf417cdc70051feca00\n" ; void *pvBuf = NULL; RTTESTI_CHECK_RC_RETV(RTManifestWriteFilesBuf(&pvBuf, &cbSize, RTDIGESTTYPE_SHA1, s_aFiles, 2), VINF_SUCCESS); /* Check returned memory size */ RTTESTI_CHECK_RETV(cbSize == strlen(s_szTestPattern)); /* Check for correct manifest file content */ RTTESTI_CHECK(memcmp(pvBuf, s_szTestPattern, cbSize) == 0); RTTestISub("Manifest verify"); RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, 0), VINF_SUCCESS); /* To little files to check */ RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 1, 0), VERR_MANIFEST_FILE_MISMATCH); /* Make the digest type invalid */ ((char*)pvBuf)[0] = 'L'; RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, 0), VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE); ((char*)pvBuf)[0] = 'S'; /* Restore */ /* Make the file name invalid */ ((char*)pvBuf)[8] = 'z'; RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, 0), VERR_MANIFEST_FILE_MISMATCH); ((char*)pvBuf)[8] = 's'; /* Restore */ /* Make the second digest invalid */ ((char*)pvBuf)[99] = '0'; RTTESTI_CHECK_RC(RTManifestVerifyFilesBuf(pvBuf, cbSize, s_aFiles, 2, &iFailed), VERR_MANIFEST_DIGEST_MISMATCH); RTTESTI_CHECK(iFailed == 1); /* Cleanup */ RTMemFree(pvBuf); }
static void test1(RTTEST hTest, const char *pszBaseDir) { char szPath1[RTPATH_MAX]; char szPath2[RTPATH_MAX]; /* * Making some assumptions about how we are executed from to start with... */ RTTestISub("Negative RTSymlinkRead, Exists & IsDangling"); char szExecDir[RTPATH_MAX]; RTTESTI_CHECK_RC_OK_RETV(RTPathExecDir(szExecDir, sizeof(szExecDir))); size_t cchExecDir = strlen(szExecDir); RTTESTI_CHECK(RTDirExists(szExecDir)); char szExecFile[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szExecFile, sizeof(szExecFile)) != NULL); size_t cchExecFile = strlen(szExecFile); RTTESTI_CHECK(RTFileExists(szExecFile)); RTTESTI_CHECK(!RTSymlinkExists(szExecFile)); RTTESTI_CHECK(!RTSymlinkExists(szExecDir)); RTTESTI_CHECK(!RTSymlinkIsDangling(szExecFile)); RTTESTI_CHECK(!RTSymlinkIsDangling(szExecDir)); RTTESTI_CHECK(!RTSymlinkExists("/")); RTTESTI_CHECK(!RTSymlinkIsDangling("/")); RTTESTI_CHECK(!RTSymlinkExists("/some/non-existing/directory/name/iprt")); RTTESTI_CHECK(!RTSymlinkExists("/some/non-existing/directory/name/iprt/")); RTTESTI_CHECK(!RTSymlinkIsDangling("/some/non-existing/directory/name/iprt")); RTTESTI_CHECK(!RTSymlinkIsDangling("/some/non-existing/directory/name/iprt/")); RTTESTI_CHECK_RC(RTSymlinkRead(szExecFile, szPath1, sizeof(szPath1), 0), VERR_NOT_SYMLINK); RTTESTI_CHECK_RC(RTSymlinkRead(szExecDir, szPath1, sizeof(szPath1), 0), VERR_NOT_SYMLINK); /* * Do some symlinking. ASSUME they are supported on the test file system. */ RTTestISub("Basics"); RTTESTI_CHECK_RETV(RTDirExists(pszBaseDir)); test1Worker(hTest, pszBaseDir, szExecFile, RTSYMLINKTYPE_FILE, false /*fDangling*/); test1Worker(hTest, pszBaseDir, szExecDir, RTSYMLINKTYPE_DIR, false /*fDangling*/); test1Worker(hTest, pszBaseDir, szExecFile, RTSYMLINKTYPE_UNKNOWN, false /*fDangling*/); test1Worker(hTest, pszBaseDir, szExecDir, RTSYMLINKTYPE_UNKNOWN, false /*fDangling*/); /* * Create a few dangling links. */ RTTestISub("Dangling links"); test1Worker(hTest, pszBaseDir, "../dangle/dangle", RTSYMLINKTYPE_FILE, true /*fDangling*/); test1Worker(hTest, pszBaseDir, "../dangle/dangle", RTSYMLINKTYPE_DIR, true /*fDangling*/); test1Worker(hTest, pszBaseDir, "../dangle/dangle", RTSYMLINKTYPE_UNKNOWN, true /*fDangling*/); test1Worker(hTest, pszBaseDir, "../dangle/dangle/", RTSYMLINKTYPE_UNKNOWN, true /*fDangling*/); }
static void tst2(void) { RTTestISub("RTGetOptArgvToString / MS_CRT"); for (size_t i = 0; i < RT_ELEMENTS(g_aMscCrtTests); i++) { char *pszCmdLine = NULL; int rc = RTGetOptArgvToString(&pszCmdLine, g_aMscCrtTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); if (!strcmp(g_aMscCrtTests[i].pszCmdLine, pszCmdLine)) tstCheckNativeMsCrtToArgv(pszCmdLine, -1, g_aMscCrtTests[i].apszArgs); else RTTestIFailed("g_aTest[%i] failed:\n" " got '%s'\n" " expected '%s'\n", i, pszCmdLine, g_aMscCrtTests[i].pszCmdLine); RTStrFree(pszCmdLine); } for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++) { char *pszCmdLine = NULL; int rc = RTGetOptArgvToString(&pszCmdLine, g_aTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); if (!strcmp(g_aTests[i].pszOutMsCrt, pszCmdLine)) tstCheckNativeMsCrtToArgv(pszCmdLine, g_aTests[i].cArgs, g_aTests[i].apszArgs); else RTTestIFailed("g_aTests[%i] failed:\n" " got |%s|\n" " expected |%s|\n", i, pszCmdLine, g_aTests[i].pszOutMsCrt); RTStrFree(pszCmdLine); } RTTestISub("RTGetOptArgvToString / BOURNE_SH"); for (size_t i = 0; i < RT_ELEMENTS(g_aTests); i++) { char *pszCmdLine = NULL; int rc = RTGetOptArgvToString(&pszCmdLine, g_aTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); if (strcmp(g_aTests[i].pszOutBourneSh, pszCmdLine)) RTTestIFailed("g_aTests[%i] failed:\n" " got |%s|\n" " expected |%s|\n", i, pszCmdLine, g_aTests[i].pszOutBourneSh); RTStrFree(pszCmdLine); } }
static void testCopyEx1(RTTEST hTest) { RTTestISub("RTStrCopyEx"); char *pszBuf4H = (char *)RTTestGuardedAllocHead(hTest, 4); char *pszBuf4T = (char *)RTTestGuardedAllocTail(hTest, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abc", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abc", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abcd", RTSTR_MAX), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abcd", RTSTR_MAX), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abcd", 3), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abcd", 3), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abcd", 2), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "ab") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abcd", 2), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "ab") == 0); }
static void test1(void) { RTTestISub("Three threads"); /* * Create the threads and let them block on the event multi semaphore. */ RTSEMEVENTMULTI hSem; RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); RTTHREAD hThread2; RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, test1Thread2, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test2"), VINF_SUCCESS); RTThreadSleep(100); RTTHREAD hThread1; RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, test1Thread1, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1"), VINF_SUCCESS); /* Force first thread (which has a timeout of 1 second) to timeout in the * first wait, and the second wait will succeed. */ RTTESTI_CHECK_RC(RTThreadSleep(1500), VINF_SUCCESS); RTTESTI_CHECK_RC(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); }
static void tstRTPipe5(void) { RTTestISub("Inherit non-standard pipe handle, read end"); char szPathSelf[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf); RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); RTHCINTPTR hNative = RTPipeToNative(hPipeR); RTTESTI_CHECK_RETV(hNative != -1); char szNative[64]; RTStrPrintf(szNative, sizeof(szNative), "%RHi", hNative); const char *papszArgs[4] = { szPathSelf, "--child-5", szNative, NULL }; RTPROCESS hChild; RTTESTI_CHECK_RC_RETV(RTProcCreate(szPathSelf, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hChild), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW, g_szTest5Message, sizeof(g_szTest5Message) - 1, NULL), VINF_SUCCESS); int rc; RTTESTI_CHECK_RC(rc = RTPipeClose(hPipeW), VINF_SUCCESS); if (RT_FAILURE(rc)) RTTESTI_CHECK_RC(RTProcTerminate(hChild), VINF_SUCCESS); RTPROCSTATUS ProcStatus; RTTESTI_CHECK_RC(rc = RTProcWait(hChild, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (RT_FAILURE(rc)) return; RTTESTI_CHECK( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0); }
static void test1(const char *pszSubTest, const char *pszFilename) { int rc; RTTestISub(pszSubTest); RTFILE hFile; rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN); if (RT_FAILURE(rc)) { if ( rc == VERR_ACCESS_DENIED || rc == VERR_PERMISSION_DENIED || rc == VERR_FILE_NOT_FOUND) { RTTestIPrintf(RTTESTLVL_ALWAYS, "Cannot access '%s', skipping.", pszFilename); return; } RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFile, pszFilename, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN), VINF_SUCCESS); } uint64_t cbFile = UINT64_MAX - 42; RTTESTI_CHECK_RC(rc = RTFileGetSize(hFile, &cbFile), VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK(cbFile != UINT64_MAX - 42); RTTestIValue(pszSubTest, cbFile, RTTESTUNIT_BYTES); } RTFileClose(hFile); RTTestISubDone(); }
static void tstRTPipe2(void) { RTTestISub("Negative"); RTPIPE hPipeR = (RTPIPE)1; RTPIPE hPipeW = (RTPIPE)1; RTTESTI_CHECK_RC(RTPipeCreate(&hPipeR, &hPipeW, ~0), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPipeCreate(NULL, &hPipeW, 0), VERR_INVALID_POINTER); RTTESTI_CHECK_RC(RTPipeCreate(&hPipeR, NULL, 0), VERR_INVALID_POINTER); RTTESTI_CHECK(hPipeR == (RTPIPE)1); RTTESTI_CHECK(hPipeW == (RTPIPE)1); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); char abBuf[_4K]; size_t cbRead = ~(size_t)3; RTTESTI_CHECK_RC(RTPipeRead(hPipeW, abBuf, 0, &cbRead), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeRead(hPipeW, abBuf, 1, &cbRead), VERR_ACCESS_DENIED); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeW, abBuf, 0, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeW, abBuf, 1, NULL), VERR_ACCESS_DENIED); size_t cbWrite = ~(size_t)5; RTTESTI_CHECK_RC(RTPipeWrite(hPipeR, "asdf", 0, &cbWrite), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeWrite(hPipeR, "asdf", 4, &cbWrite), VERR_ACCESS_DENIED); RTTESTI_CHECK(cbWrite == ~(size_t)5); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeR, "asdf", 0, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeR, "asdf", 4, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeFlush(hPipeR), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
static void tstRTProcQueryUsername(void) { RTTestISub("Basics"); size_t cbUser; char szUser[1024]; memset(szUser, '-', sizeof(szUser)); /* negative stuff that may assert: */ bool fMayPanic = RTAssertSetMayPanic(false); bool fQuiet = RTAssertSetQuiet(true); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), NULL, 8, &cbUser), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), szUser, 0, &cbUser), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), NULL, 0, NULL), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTProcQueryUsernameA(RTProcSelf(), NULL), VERR_INVALID_POINTER); RTAssertSetMayPanic(fMayPanic); RTAssertSetQuiet(fQuiet); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), NULL, 0, &cbUser), VERR_BUFFER_OVERFLOW); memset(szUser, '-', sizeof(szUser)); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), szUser, cbUser - 1, &cbUser), VERR_BUFFER_OVERFLOW); memset(szUser, '-', sizeof(szUser)); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), szUser, sizeof(szUser), &cbUser), VINF_SUCCESS); RTTestPrintf(NULL, RTTESTLVL_ALWAYS, "Username: %s\n", szUser); /* */ char *pszUser = NULL; RTTESTI_CHECK_RC(RTProcQueryUsernameA(RTProcSelf(), &pszUser), VINF_SUCCESS); RTTestPrintf(NULL, RTTESTLVL_ALWAYS, "Username: %s\n", pszUser); RTTESTI_CHECK(strcmp(pszUser, szUser) == 0); RTStrFree(pszUser); }
static void doStandaloneTests(void) { RTTestISub("Standalone"); PCFGMNODE pRoot;; RTTESTI_CHECK_RETV((pRoot = CFGMR3CreateTree(NULL)) != NULL); doGeneralTests(pRoot); CFGMR3DestroyTree(pRoot); }
static void testBasics(void) { RTTestISub("Basics"); RTSEMEVENTMULTI hSem; RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); /* The semaphore is created in a reset state, calling reset explicitly shouldn't make any difference. */ testBasicsWaitTimeout(hSem, 0); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 1); if (RTTestIErrorCount()) return; /* When signalling the semaphore all successive wait calls shall succeed, signalling it again should make no difference. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); testBasicsWaitSuccess(hSem, 2); if (RTTestIErrorCount()) return; /* After resetting it we should time out again. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 3); if (RTTestIErrorCount()) return; /* The number of resets or signal calls shouldn't matter. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 4); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); testBasicsWaitSuccess(hSem, 5); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 6); /* Destroy it. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(NIL_RTSEMEVENTMULTI), VINF_SUCCESS); /* Whether it is reset (above), signalled or not used shouldn't matter. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); RTTestISubDone(); }
/** * Check hash and memory performance. */ static void tst2(void) { RTTestISub("Hash performance"); /* * Generate test strings using a specific pseudo random generator. */ size_t cbStrings = 0; char *apszTests[8192]; RTRAND hRand; RTTESTI_CHECK_RC_RETV(RTRandAdvCreateParkMiller(&hRand), VINF_SUCCESS); for (uint32_t i = 0; i < 8192; i++) { char szBuf[8192]; uint32_t cch = RTRandAdvU32Ex(hRand, 3, sizeof(szBuf) - 1); RTRandAdvBytes(hRand, szBuf, cch); szBuf[cch] = '\0'; for (uint32_t off = 0; off < cch; off++) { uint8_t b = szBuf[off]; b &= 0x7f; if (!b || b == 0x7f) b = ' '; else if (RTLocCIsCntrl(b) && b != '\n' && b != '\r' && b != '\t') b += 0x30; szBuf[off] = b; } apszTests[i] = (char *)RTMemDup(szBuf, cch + 1); RTTESTI_CHECK_RETV(apszTests[i] != NULL); cbStrings += cch + 1; } RTRandAdvDestroy(hRand); RTTestIValue("Average string", cbStrings / RT_ELEMENTS(apszTests), RTTESTUNIT_BYTES); /* * Test new insertion first time around. */ RTSTRCACHE hStrCache; RTTESTI_CHECK_RC_RETV(RTStrCacheCreate(&hStrCache, "hash performance"), VINF_SUCCESS); uint64_t nsTsStart = RTTimeNanoTS(); for (uint32_t i = 0; i < RT_ELEMENTS(apszTests); i++) RTTESTI_CHECK_RETV(RTStrCacheEnter(hStrCache, apszTests[i]) != NULL); uint64_t cNsElapsed = RTTimeNanoTS() - nsTsStart; RTTestIValue("First insert", cNsElapsed / RT_ELEMENTS(apszTests), RTTESTUNIT_NS_PER_CALL); /* * Insert existing strings. */ nsTsStart = RTTimeNanoTS(); for (uint32_t i = 0; i < 8192; i++) RTTESTI_CHECK(RTStrCacheEnter(hStrCache, apszTests[i]) != NULL); cNsElapsed = RTTimeNanoTS() - nsTsStart; RTTestIValue("Duplicate insert", cNsElapsed / RT_ELEMENTS(apszTests), RTTESTUNIT_NS_PER_CALL); tstShowStats(hStrCache); RTTESTI_CHECK_RC(RTStrCacheDestroy(hStrCache), VINF_SUCCESS); }
static void testCat1(RTTEST hTest) { RTTestISub("RTStrCat"); char *pszBuf4H = (char *)RTTestGuardedAllocHead(hTest, 4); char *pszBuf4T = (char *)RTTestGuardedAllocTail(hTest, 4); memset(pszBuf4T, 0xff, 4); *pszBuf4T = '\0'; RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, "abc"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); memset(pszBuf4H, 0xff, 4); *pszBuf4H = '\0'; RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, "abc"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); memset(pszBuf4T, 0xff, 4); strcpy(pszBuf4T, "a"); memset(pszBuf4H, 0xff, 4); strcpy(pszBuf4H, "a"); RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, "bc"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, "bc"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); memset(pszBuf4T, 0xff, 4); strcpy(pszBuf4T, "ab"); memset(pszBuf4H, 0xff, 4); strcpy(pszBuf4H, "ab"); RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, "c"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, "c"), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); memset(pszBuf4T, 0xff, 4); strcpy(pszBuf4T, "abc"); memset(pszBuf4H, 0xff, 4); strcpy(pszBuf4H, "abc"); RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, ""), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, ""), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); memset(pszBuf4T, 0xff, 4); strcpy(pszBuf4T, ""); memset(pszBuf4H, 0xff, 4); strcpy(pszBuf4H, ""); RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, "abcd"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, "abcd"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); memset(pszBuf4T, 0xff, 4); strcpy(pszBuf4T, "ab"); memset(pszBuf4H, 0xff, 4); strcpy(pszBuf4H, "ab"); RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, "cd"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, "cd"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); memset(pszBuf4T, 0xff, 4); strcpy(pszBuf4T, "abc"); memset(pszBuf4H, 0xff, 4); strcpy(pszBuf4H, "abc"); RTTESTI_CHECK_RC(RTStrCat(pszBuf4H, 4, "d"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCat(pszBuf4T, 4, "d"), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); }
/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(void) { RTTestISub("Basics"); /* Create one without constructor or destructor. */ uint32_t const cObjects = PAGE_SIZE * 2 / 256; RTMEMCACHE hMemCache; RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&hMemCache, 256, cObjects, 32, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(hMemCache != NIL_RTMEMCACHE); /* Allocate a bit and free it again. */ void *pv = NULL; RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(hMemCache, &pv), VINF_SUCCESS); RTTESTI_CHECK_RETV(pv != NULL); RTTESTI_CHECK_RETV(RT_ALIGN_P(pv, 32) == pv); RTMemCacheFree(hMemCache, pv); RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) != NULL); RTMemCacheFree(hMemCache, pv); /* Allocate everything and free it again, checking size constraints. */ for (uint32_t iLoop = 0; iLoop < 20; iLoop++) { /* Allocate everything. */ void *apv[cObjects]; for (uint32_t i = 0; i < cObjects; i++) { apv[i] = NULL; RTTESTI_CHECK_RC(RTMemCacheAllocEx(hMemCache, &apv[i]), VINF_SUCCESS); } /* Check that we've got it all. */ int rc; RTTESTI_CHECK_RC(rc = RTMemCacheAllocEx(hMemCache, &pv), VERR_MEM_CACHE_MAX_SIZE); if (RT_SUCCESS(rc)) RTMemCacheFree(hMemCache, pv); RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) == NULL); RTMemCacheFree(hMemCache, pv); /* Free all the allocations. */ for (uint32_t i = 0; i < cObjects; i++) { RTMemCacheFree(hMemCache, apv[i]); RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) != NULL); RTMemCacheFree(hMemCache, pv); } } /* Destroy it. */ RTTESTI_CHECK_RC(RTMemCacheDestroy(hMemCache), VINF_SUCCESS); RTTESTI_CHECK_RC(RTMemCacheDestroy(NIL_RTMEMCACHE), VINF_SUCCESS); }
static void tstRTCreateProcEx2(const char *pszAsUser, const char *pszPassword) { RTTestISub("Standard Err"); RTPIPE hPipeR, hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); const char * apszArgs[3] = { "non-existing-non-executable-file", "--testcase-child-2", NULL }; RTHANDLE Handle; Handle.enmType = RTHANDLETYPE_PIPE; Handle.u.hPipe = hPipeW; RTPROCESS hProc; RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); char szOutput[_4K]; size_t offOutput = 0; for (;;) { size_t cbLeft = sizeof(szOutput) - 1 - offOutput; RTTESTI_CHECK(cbLeft > 0); if (cbLeft == 0) break; size_t cbRead; int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead); if (RT_FAILURE(rc)) { RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE); break; } offOutput += cbRead; } szOutput[offOutput] = '\0'; RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND }; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); RTThreadSleep(10); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); else if ( offOutput != sizeof("howdy") - 1 || strcmp(szOutput, "howdy")) RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput); else RTTestIPassed(NULL); }
static void tstRTCreateProcEx4(const char *pszAsUser, const char *pszPassword) { RTTestISub("Argument with spaces and stuff"); RTPROCESS hProc; RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, g_apszArgs4, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND }; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); }
static void testDisas(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode) { RTTestISub(pszSub); size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs; for (size_t off = 0; off < cbInstrs;) { uint32_t const cErrBefore = RTTestIErrorCount(); uint32_t cb = 1; DISSTATE Dis; char szOutput[256] = {0}; int rc = DISInstrToStr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb, szOutput, sizeof(szOutput)); RTTESTI_CHECK_RC(rc, VINF_SUCCESS); RTTESTI_CHECK(cb == Dis.cbInstr); RTTESTI_CHECK(cb > 0); RTTESTI_CHECK(cb <= 16); RTStrStripR(szOutput); RTTESTI_CHECK(szOutput[0]); if (szOutput[0]) { char *pszBytes = strchr(szOutput, '['); RTTESTI_CHECK(pszBytes); if (pszBytes) { RTTESTI_CHECK(pszBytes[-1] == ' '); RTTESTI_CHECK(RT_C_IS_XDIGIT(pszBytes[1])); RTTESTI_CHECK(pszBytes[cb * 3] == ']'); RTTESTI_CHECK(pszBytes[cb * 3 + 1] == ' '); size_t cch = strlen(szOutput); RTTESTI_CHECK(szOutput[cch - 1] != ','); } } if (cErrBefore != RTTestIErrorCount()) RTTestIFailureDetails("rc=%Rrc, off=%#x (%u) cbInstr=%u enmDisCpuMode=%d\n", rc, off, Dis.cbInstr, enmDisCpuMode); RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput); /* Check with size-only. */ uint32_t cbOnly = 1; DISSTATE DisOnly; rc = DISInstrWithPrefetchedBytes((uintptr_t)&pabInstrs[off], enmDisCpuMode, 0 /*fFilter - none */, Dis.abInstr, Dis.cbCachedInstr, NULL, NULL, &DisOnly, &cbOnly); RTTESTI_CHECK_RC(rc, VINF_SUCCESS); RTTESTI_CHECK(cbOnly == DisOnly.cbInstr); RTTESTI_CHECK_MSG(cbOnly == cb, ("%#x vs %#x\n", cbOnly, cb)); off += cb; } }
/** * Test automatic cleanup upon destruction. */ static void tst3(void) { RTTestISub("Destroy non-empty pool"); /* * Nothing freed. */ RTMEMPOOL hMemPool; RTTESTI_CHECK_RC_RETV(RTMemPoolCreate(&hMemPool, "test 3a"), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 10)); RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 20)); RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 40)); RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 80)); RTTESTI_CHECK_RC_RETV(RTMemPoolDestroy(hMemPool), VINF_SUCCESS); /* * Pseudo random freeing to test list maintenance. */ RTRAND hRand; RTTESTI_CHECK_RC_OK_RETV(RTRandAdvCreateParkMiller(&hRand)); for (uint32_t i = 0; i < 10; i++) { RTTESTI_CHECK_RC_RETV(RTMemPoolCreate(&hMemPool, "test 3b"), VINF_SUCCESS); void *apvHistory[256]; RT_ZERO(apvHistory); uint32_t cBlocks = 0; uint32_t j; for (j = 0; j < RT_ELEMENTS(apvHistory) - i * 7; j++) { RTTESTI_CHECK_RETV(apvHistory[j] = RTMemPoolAlloc(hMemPool, j)); memset(apvHistory[j], 'a', j); cBlocks++; if (RTRandAdvU32Ex(hRand, 0, 4) == 4) { uint32_t iFree = RTRandAdvU32Ex(hRand, 0, j); cBlocks -= apvHistory[iFree] != NULL; RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, apvHistory[iFree]) == 0); apvHistory[iFree] = NULL; } } RTTESTI_CHECK_RC_RETV(RTMemPoolDestroy(hMemPool), VINF_SUCCESS); RTTestIPrintf(RTTESTLVL_INFO, "cBlocks=%u j=%u\n", cBlocks, j); } RTRandAdvDestroy(hRand); }
static void tstRTPipe4(void) { RTTestISub("Inherit non-standard pipe handle, write end"); char szPathSelf[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf); RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); RTHCINTPTR hNative = RTPipeToNative(hPipeW); RTTESTI_CHECK_RETV(hNative != -1); char szNative[64]; RTStrPrintf(szNative, sizeof(szNative), "%RHi", hNative); const char *papszArgs[4] = { szPathSelf, "--child-4", szNative, NULL }; RTPROCESS hChild; RTTESTI_CHECK_RC_RETV(RTProcCreate(szPathSelf, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hChild), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); char szTmp[1024]; size_t cbRead = 0; int rc; RTTESTI_CHECK_RC(rc = RTPipeReadBlocking(hPipeR, szTmp, sizeof(szTmp) - 1, &cbRead), VINF_SUCCESS); if (RT_FAILURE(rc)) cbRead = 0; RTTESTI_CHECK_RETV(cbRead < sizeof(szTmp)); szTmp[cbRead] = '\0'; size_t cbRead2; char szTmp2[4]; RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeR, szTmp2, sizeof(szTmp2), &cbRead2), VERR_BROKEN_PIPE); RTTESTI_CHECK_RC(rc = RTPipeClose(hPipeR), VINF_SUCCESS); if (RT_FAILURE(rc)) RTTESTI_CHECK_RC(RTProcTerminate(hChild), VINF_SUCCESS); RTPROCSTATUS ProcStatus; RTTESTI_CHECK_RC(rc = RTProcWait(hChild, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (RT_FAILURE(rc)) return; RTTESTI_CHECK( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0); if (memcmp(szTmp, g_szTest4Message, sizeof(g_szTest4Message))) RTTestIFailed("Message mismatch.\n:Expected '%s'\nGot '%s'\n", g_szTest4Message, szTmp); }
static void tstDirCreateTemp(const char *pszSubTest, const char *pszTemplate, unsigned cTimes, bool fSkipXCheck) { RTTestISub(pszSubTest); /* Allocate the result array. */ char **papszNames = (char **)RTMemTmpAllocZ(cTimes * sizeof(char *)); RTTESTI_CHECK_RETV(papszNames != NULL); /* The test loop. */ unsigned i; for (i = 0; i < cTimes; i++) { int rc; char szName[RTPATH_MAX]; RTTESTI_CHECK_RC(rc = RTPathAppend(strcpy(szName, g_szTempPath), sizeof(szName), pszTemplate), VINF_SUCCESS); if (RT_FAILURE(rc)) break; RTTESTI_CHECK(papszNames[i] = RTStrDup(szName)); if (!papszNames[i]) break; rc = RTDirCreateTemp(papszNames[i]); if (rc != VINF_SUCCESS) { RTTestIFailed("RTDirCreateTemp(%s) call #%u -> %Rrc\n", szName, i, rc); RTStrFree(papszNames[i]); papszNames[i] = NULL; break; } RTTestIPrintf(RTTESTLVL_DEBUG, "%s\n", papszNames[i]); RTTESTI_CHECK_MSG(strlen(szName) == strlen(papszNames[i]), ("szName %s\nReturned %s\n", szName, papszNames[i])); if (!fSkipXCheck) RTTESTI_CHECK_MSG(strchr(RTPathFilename(papszNames[i]), 'X') == NULL, ("szName %s\nReturned %s\n", szName, papszNames[i])); } /* cleanup */ while (i-- > 0) { RTTESTI_CHECK_RC(RTDirRemove(papszNames[i]), VINF_SUCCESS); RTStrFree(papszNames[i]); } RTMemTmpFree(papszNames); }
static void tstRTPipe3(void) { RTTestISub("Full write buffer"); RTPIPE hPipeR = (RTPIPE)999999; RTPIPE hPipeW = (RTPIPE)999999; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); static char s_abBuf[_256K]; int rc = VINF_SUCCESS; size_t cbTotal = 0; memset(s_abBuf, 0xff, sizeof(s_abBuf)); for (;;) { RTTESTI_CHECK(cbTotal < _1G); if (cbTotal > _1G) break; size_t cbWritten = _1G; rc = RTPipeWrite(hPipeW, s_abBuf, sizeof(s_abBuf), &cbWritten); RTTESTI_CHECK_MSG(rc == VINF_SUCCESS || rc == VINF_TRY_AGAIN, ("rc=%Rrc\n", rc)); if (rc != VINF_SUCCESS) break; cbTotal += cbWritten; } if (rc == VINF_TRY_AGAIN) { RTTestIPrintf(RTTESTLVL_ALWAYS, "cbTotal=%zu (%#zx)\n", cbTotal, cbTotal); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 1), VERR_TIMEOUT); size_t cbRead; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, s_abBuf, RT_MIN(sizeof(s_abBuf), cbTotal) / 2, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 1), VINF_SUCCESS); size_t cbWritten = _1G; rc = RTPipeWrite(hPipeW, s_abBuf, sizeof(s_abBuf), &cbWritten); RTTESTI_CHECK(rc == VINF_SUCCESS); } RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
static void test2(void) { RTTestISub("< 0"); for (int ch = -1; ch > -2000000; ch--) { RTTESTI_CHECK(!RT_C_IS_CNTRL(ch)); RTTESTI_CHECK(!RT_C_IS_SPACE(ch)); RTTESTI_CHECK(!RT_C_IS_BLANK(ch)); RTTESTI_CHECK(!RT_C_IS_PRINT(ch)); RTTESTI_CHECK(!RT_C_IS_PUNCT(ch)); RTTESTI_CHECK(!RT_C_IS_GRAPH(ch)); RTTESTI_CHECK(!RT_C_IS_DIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_XDIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ODIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ALPHA(ch)); RTTESTI_CHECK(!RT_C_IS_UPPER(ch)); RTTESTI_CHECK(!RT_C_IS_LOWER(ch)); } }
static void test3(void) { RTTestISub("> 127"); for (int ch = 128; ch < 2000000; ch++) { RTTESTI_CHECK(!RT_C_IS_CNTRL(ch)); RTTESTI_CHECK(!RT_C_IS_SPACE(ch)); RTTESTI_CHECK(!RT_C_IS_BLANK(ch)); RTTESTI_CHECK(!RT_C_IS_PRINT(ch)); RTTESTI_CHECK(!RT_C_IS_PUNCT(ch)); RTTESTI_CHECK(!RT_C_IS_GRAPH(ch)); RTTESTI_CHECK(!RT_C_IS_DIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_XDIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ODIGIT(ch)); RTTESTI_CHECK(!RT_C_IS_ALPHA(ch)); RTTESTI_CHECK(!RT_C_IS_UPPER(ch)); RTTESTI_CHECK(!RT_C_IS_LOWER(ch)); } }
static void test1(void) { RTTestISub("ASCII range"); for (int ch = 0; ch < (int)RT_ELEMENTS(g_afCharMap); ch++) { TEST_X(ch, RT_C_IS_CNTRL, X_CNTRL); TEST_X(ch, RT_C_IS_SPACE, X_SPACE); TEST_X(ch, RT_C_IS_BLANK, X_BLANK); TEST_X(ch, RT_C_IS_PRINT, X_PRINT); TEST_X(ch, RT_C_IS_PUNCT, X_PUNCT); TEST_X(ch, RT_C_IS_GRAPH, X_GRAPH); TEST_X(ch, RT_C_IS_DIGIT, X_DIGIT); TEST_X(ch, RT_C_IS_XDIGIT, X_XDIGIT); TEST_X(ch, RT_C_IS_ODIGIT, X_ODIGIT); TEST_X(ch, RT_C_IS_ALPHA, X_ALPHA); TEST_X(ch, RT_C_IS_UPPER, X_UPPER); TEST_X(ch, RT_C_IS_LOWER, X_LOWER); } }
/** * Test constructor / destructor. */ static void tst2(void) { RTTestISub("Ctor/Dtor"); /* Create one without constructor or destructor. */ bool fFail = false; uint32_t const cObjects = PAGE_SIZE * 2 / 256; RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, 256, cObjects, 32, tst2Ctor, tst2Dtor, &fFail, 0 /*fFlags*/), VINF_SUCCESS); /* A failure run first. */ fFail = true; void *pv = (void *)0x42; RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(g_hMemCache, &pv), VERR_RESOURCE_BUSY); RTTESTI_CHECK(pv == (void *)0x42); fFail = false; /* To two rounds where we allocate all the objects and free them again. */ for (uint32_t iLoop = 0; iLoop < 2; iLoop++) { void *apv[cObjects]; for (uint32_t i = 0; i < cObjects; i++) { apv[i] = NULL; RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(g_hMemCache, &apv[i]), VINF_SUCCESS); if (iLoop == 0) RTTESTI_CHECK(!strcmp((char *)apv[i], "ctor was called\n")); else RTTESTI_CHECK(!strcmp((char *)apv[i], "ctor was called\nused\n")); strcat((char *)apv[i], "used\n"); } RTTESTI_CHECK_RETV((pv = RTMemCacheAlloc(g_hMemCache)) == NULL); RTMemCacheFree(g_hMemCache, pv); for (uint32_t i = 0; i < cObjects; i++) RTMemCacheFree(g_hMemCache, apv[i]); } /* Cone, destroy the cache. */ RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS); }
static void test0(void) { RTTestISub("Verify test data"); RTTESTI_CHECK(setlocale(LC_ALL, "C") != NULL); for (int ch = 0; ch < (int)RT_ELEMENTS(g_afCharMap); ch++) { TEST_X(ch, iscntrl, X_CNTRL); TEST_X(ch, isspace, X_SPACE); TEST_X(ch, isblank, X_BLANK); TEST_X(ch, isprint, X_PRINT); TEST_X(ch, ispunct, X_PUNCT); TEST_X(ch, isgraph, X_GRAPH); TEST_X(ch, isdigit, X_DIGIT); TEST_X(ch, isxdigit, X_XDIGIT); /*TEST_X(ch, isodigit, X_ODIGIT);*/ TEST_X(ch, isalpha, X_ALPHA); TEST_X(ch, isupper, X_UPPER); TEST_X(ch, islower, X_LOWER); } }
static void testVectorDeleteValue(RTTEST hTest) { RTTestISub("Vector structure with cleanup by value callback"); struct tstDeleteValue myVec = RTVEC_INITIALIZER; void **ppvVal; ppvVal = tstDeleteValuePushBack(&myVec); /* AssertPtrReturnVoid(ppvVal); */ *ppvVal = (void *)1; ppvVal = tstDeleteValuePushBack(&myVec); /* AssertPtrReturnVoid(ppvVal); */ *ppvVal = (void *)3; ppvVal = tstDeleteValuePushBack(&myVec); /* AssertPtrReturnVoid(ppvVal); */ *ppvVal = (void *)2; s_cDeleteCalls = 0; tstDeleteValuePopBack(&myVec); RTTESTI_CHECK(s_cDeleteCalls == 1); RTTESTI_CHECK(s_apvDeleteArg[0] == (void *)2); RTTESTI_CHECK( tstDeleteValueBegin(&myVec) + 2 == tstDeleteValueEnd(&myVec)); RTTESTI_CHECK(*tstDeleteValueBegin(&myVec) == (void *)1); RTTESTI_CHECK(*(tstDeleteValueEnd(&myVec) - 1) == (void *)3); s_cDeleteCalls = 0; tstDeleteValueClear(&myVec); RTTESTI_CHECK(s_cDeleteCalls == 2); RTTESTI_CHECK(s_apvDeleteArg[0] == (void *)1); RTTESTI_CHECK(s_apvDeleteArg[1] == (void *)3); RTTESTI_CHECK(tstDeleteValueBegin(&myVec) == tstDeleteValueEnd(&myVec)); ppvVal = tstDeleteValuePushBack(&myVec); /* AssertPtrReturnVoid(ppvVal); */ RTTESTI_CHECK(ppvVal == tstDeleteValueBegin(&myVec)); RTTESTI_CHECK(ppvVal + 1 == tstDeleteValueEnd(&myVec)); }
static void tstRTPipe1(void) { RTTestISub("Basics"); RTPIPE hPipeR = NIL_RTPIPE; RTPIPE hPipeW = NIL_RTPIPE; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RETV(hPipeR != NIL_RTPIPE); RTTESTI_CHECK_RETV(hPipeW != NIL_RTPIPE); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(NIL_RTPIPE), VINF_SUCCESS); hPipeR = NIL_RTPIPE; hPipeW = NIL_RTPIPE; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ | RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); int rc = RTPipeFlush(hPipeW); RTTESTI_CHECK_MSG(rc == VERR_NOT_SUPPORTED || rc == VINF_SUCCESS, ("%Rrc\n", rc)); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeW, 1), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); size_t cbRead = ~(size_t)0; char abBuf[_64K + _4K]; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_TRY_AGAIN); RTTESTI_CHECK_RETV(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 1, &cbRead), VINF_TRY_AGAIN); RTTESTI_CHECK_RETV(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 0); size_t cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, abBuf, 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 0); /* We can write a number of bytes without blocking (see PIPE_BUF on POSIX systems). */ cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "42", 2, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_MSG_RETV(cbWritten == 2, ("cbWritten=%zu\n", cbWritten)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "!", 1, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 3, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 3); RTTESTI_CHECK_RETV(!memcmp(abBuf, "42!", 3)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "BigQ", 4, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 4); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 4); RTTESTI_CHECK_RETV(!memcmp(abBuf, "BigQ", 4)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "H2G2", 4, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 4); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 1, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 2, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[2], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 3, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[3], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); RTTESTI_CHECK_RETV(!memcmp(abBuf, "H2G2", 4)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 4, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTestISub("VERR_BROKEN_PIPE"); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "", 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 0); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "4", 1, &cbWritten), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbWritten == ~(size_t)2); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)3; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "42", 2, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 2); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); RTTESTI_CHECK(!memcmp(abBuf, "42", 2)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)3; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTestISub("Blocking"); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "42!", 3, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 3); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, abBuf, 3, NULL), VINF_SUCCESS); RTTESTI_CHECK(!memcmp(abBuf, "42!", 3)); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 0, NULL), VINF_SUCCESS); cbRead = ~(size_t)42; RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 1, NULL), VERR_BROKEN_PIPE); cbRead = ~(size_t)42; RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 1, &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == 0); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42!", 3, NULL), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 3); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[1], 1, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[2], 1, NULL), VINF_SUCCESS); RTTESTI_CHECK(!memcmp(abBuf, "42!", 3)); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "", 0, NULL), VINF_SUCCESS); cbWritten = ~(size_t)9; RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "", 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 0); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42", 2, NULL), VERR_BROKEN_PIPE); cbWritten = ~(size_t)9; RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42", 2, &cbWritten), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbWritten == 0); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
static void tstRTPoll2(void) { RTTestISub("Negative"); /* * Bad set pointer and handle values. */ RTTESTI_CHECK_RC(RTPollSetCreate(NULL), VERR_INVALID_POINTER); RTPOLLSET hSetInvl = (RTPOLLSET)(intptr_t)-3; RTTESTI_CHECK_RC(RTPollSetDestroy(hSetInvl), VERR_INVALID_HANDLE); RTHANDLE Handle; Handle.enmType = RTHANDLETYPE_PIPE; Handle.u.hPipe = NIL_RTPIPE; RTTESTI_CHECK_RC(RTPollSetAdd(hSetInvl, &Handle, RTPOLL_EVT_ERROR, 1), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollSetRemove(hSetInvl, 1), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSetInvl, 1, NULL), VERR_INVALID_HANDLE); RTTESTI_CHECK(RTPollSetGetCount(hSetInvl) == UINT32_MAX); RTTESTI_CHECK_RC(RTPoll(hSetInvl, 0, NULL, NULL), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollNoResume(hSetInvl, 0, NULL, NULL), VERR_INVALID_HANDLE); /* * Invalid arguments and other stuff. */ RTPOLLSET hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VERR_DEADLOCK); RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VERR_DEADLOCK); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, UINT32_MAX), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 1), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, NULL, RTPOLL_EVT_ERROR, 1), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_ERROR, UINT32_MAX), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, UINT32_MAX, 3), VERR_INVALID_PARAMETER); Handle.enmType = RTHANDLETYPE_INVALID; RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_ERROR, 3), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, NULL, RTPOLL_EVT_ERROR, UINT32_MAX), VERR_INVALID_PARAMETER); /* duplicate id */ RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 0), VERR_POLL_HANDLE_ID_EXISTS); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VINF_SUCCESS); RTPipeClose(hPipeR); RTPipeClose(hPipeW); /* non-pollable handle */ RTFILE hBitBucket; RTTESTI_CHECK_RC_RETV(RTFileOpenBitBucket(&hBitBucket, RTFILE_O_WRITE), VINF_SUCCESS); Handle.enmType = RTHANDLETYPE_FILE; Handle.u.hFile = hBitBucket; RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_WRITE, 10), VERR_POLL_HANDLE_NOT_POLLABLE); RTFileClose(hBitBucket); RTTESTI_CHECK_RC_RETV(RTPollSetDestroy(hSet), VINF_SUCCESS); }
static void tstRTPoll1(void) { RTTestISub("Basics"); /* create and destroy. */ RTPOLLSET hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetDestroy(NIL_RTPOLLSET), VINF_SUCCESS); /* empty set, adding a NIL handle. */ hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 0, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, NIL_RTPIPE, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); /* * Set with pipes */ RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); /* add the read pipe */ RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS); RTHANDLE Handle; RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); /* poll on the set, should time out. */ RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL, NULL), VERR_TIMEOUT); /* add the write pipe with error detection only, check that poll still times out. remove it again. */ RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_ERROR, 11 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 11 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 11), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); /* add the write pipe */ RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 10 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 10 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); /* poll on the set again, now it should indicate hPipeW is ready. */ int rc; RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPoll(hSet, 100, NULL, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 100, NULL, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VINF_SUCCESS); uint32_t fEvents = UINT32_MAX; uint32_t id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPoll(hSet, 250, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); } fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 100, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); } /* Write to the pipe. Currently ASSUMING we'll get the read ready now... Good idea? */ RTTESTI_CHECK_RC(rc = RTPipeWriteBlocking(hPipeW, "hello", 5, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPoll(hSet, 256, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); } fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 383, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); } } /* Remove the read pipe, do a quick poll check. */ RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); /* Add it back and check that we now get the write handle when polling. (Is this FIFOing a good idea?) */ RTTESTI_CHECK_RC_RETV(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 555, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); /* Remove it again and break the pipe by closing the read end. */ RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK_MSG( fEvents == RTPOLL_EVT_ERROR \ || fEvents == (RTPOLL_EVT_ERROR | RTPOLL_EVT_WRITE), ("%#x\n", fEvents)); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); /* * Check FIFO order when removing and adding. * * Note! FIFO order is not guaranteed when a handle has more than one entry * in the set. */ RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); RTPIPE hPipeR2, hPipeW2; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR2, &hPipeW2, 0/*fFlags*/), VINF_SUCCESS); RTPIPE hPipeR3, hPipeW3; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR3, &hPipeW3, 0/*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 2 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR2, RTPOLL_EVT_READ, 3 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW2, RTPOLL_EVT_WRITE, 4 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR3, RTPOLL_EVT_READ, 5 /*id*/), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 2); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW, "hello", 5, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW2, "hello", 5, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW3, "hello", 5, NULL), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 1), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 2); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 2), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 3); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 3), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 4); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 4), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 5); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 5), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW2), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR2), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW3), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR3), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); }