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); }
/** * 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 tstCheckNativeMsCrtToArgv(const char *pszCmdLine, int cExpectedArgs, const char * const *papszExpectedArgs) { #ifdef RT_OS_WINDOWS /* * Resolve APIs. */ static void *(__stdcall * s_pfnLocalFree)(void *pvFree); static PRTUTF16 *(__stdcall * s_pfnCommandLineToArgvW)(PCRTUTF16 pwszCmdLine, int *pcArgs); if (!s_pfnCommandLineToArgvW) { *(void **)&s_pfnLocalFree = RTLdrGetSystemSymbol("kernel32.dll", "LocalFree"); RTTESTI_CHECK_RETV(s_pfnLocalFree != NULL); *(void **)&s_pfnCommandLineToArgvW = RTLdrGetSystemSymbol("shell32.dll", "CommandLineToArgvW"); RTTESTI_CHECK_RETV(s_pfnCommandLineToArgvW != NULL); } /* * Calc expected arguments if needed. */ if (cExpectedArgs == -1) for (cExpectedArgs = 0; papszExpectedArgs[cExpectedArgs]; cExpectedArgs++) { /* nothing */ } /* * Convert input command line to UTF-16 and call native API. */ RTUTF16 wszCmdLine[1024]; PRTUTF16 pwszCmdLine = &wszCmdLine[1]; RTTESTI_CHECK_RC_RETV(RTStrToUtf16Ex(pszCmdLine, RTSTR_MAX, &pwszCmdLine, 1023, NULL), VINF_SUCCESS); wszCmdLine[0] = ' '; int cArgs = -2; PRTUTF16 *papwszArgs = s_pfnCommandLineToArgvW(wszCmdLine, &cArgs); /* * Check the result. */ if (cArgs - 1 != cExpectedArgs) RTTestIFailed("Native returns cArgs=%d, expected %d (cmdline=|%s|)", cArgs - 1, cExpectedArgs, pszCmdLine); int cArgsCheck = RT_MIN(cArgs - 1, cExpectedArgs); for (int i = 0; i < cArgsCheck; i++) { char *pszArg = NULL; RTTESTI_CHECK_RC_RETV(RTUtf16ToUtf8(papwszArgs[i + 1], &pszArg), VINF_SUCCESS); if (strcmp(pszArg, papszExpectedArgs[i])) RTTestIFailed("Native returns argv[%i]='%s', expected '%s' (cmdline=|%s|)", i, pszArg, papszExpectedArgs[i], pszCmdLine); RTStrFree(pszArg); } if (papwszArgs) s_pfnLocalFree(papwszArgs); #else NOREF(pszCmdLine); NOREF(cExpectedArgs); NOREF(papszExpectedArgs); #endif }
/** * 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 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 doGeneralTests(PCFGMNODE pRoot) { /* test multilevel node creation */ PCFGMNODE pChild = NULL; RTTESTI_CHECK_RC_RETV(CFGMR3InsertNode(pRoot, "First/Second/Third//Final", &pChild), VINF_SUCCESS); RTTESTI_CHECK_RETV(RT_VALID_PTR(pChild)); RTTESTI_CHECK(CFGMR3GetChild(pRoot, "First/Second/Third/Final") == pChild); /* * Boolean queries. */ RTTESTI_CHECK_RC(CFGMR3InsertInteger(pChild, "BoolValue", 1), VINF_SUCCESS); bool f = false; RTTESTI_CHECK_RC(CFGMR3QueryBool(pChild, "BoolValue", &f), VINF_SUCCESS); RTTESTI_CHECK(f == true); RTTESTI_CHECK_RC(CFGMR3QueryBool(pRoot, "BoolValue", &f), VERR_CFGM_VALUE_NOT_FOUND); RTTESTI_CHECK_RC(CFGMR3QueryBool(NULL, "BoolValue", &f), VERR_CFGM_NO_PARENT); RTTESTI_CHECK_RC(CFGMR3QueryBoolDef(pChild, "ValueNotFound", &f, true), VINF_SUCCESS); RTTESTI_CHECK(f == true); RTTESTI_CHECK_RC(CFGMR3QueryBoolDef(pChild, "ValueNotFound", &f, false), VINF_SUCCESS); RTTESTI_CHECK(f == false); RTTESTI_CHECK_RC(CFGMR3QueryBoolDef(NULL, "BoolValue", &f, true), VINF_SUCCESS); RTTESTI_CHECK(f == true); RTTESTI_CHECK_RC(CFGMR3QueryBoolDef(NULL, "BoolValue", &f, false), VINF_SUCCESS); RTTESTI_CHECK(f == false); }
static void tstRTCreateProcEx5(const char *pszUser, const char *pszPassword) { RTTestISubF("As user \"%s\" with password \"%s\"", pszUser, pszPassword); RTTESTI_CHECK_RETV(pszUser && *pszUser); const char * apszArgs[] = { "test", /* user name */ "--testcase-child-5", pszUser, NULL }; /* Test for invalid logons. */ RTPROCESS hProc; int rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, "non-existing-user", "wrong-password", &hProc); if (rc != VERR_AUTHENTICATION_FAILURE && rc != VERR_PRIVILEGE_NOT_HELD && rc != VERR_PROC_TCB_PRIV_NOT_HELD) RTTestIFailed("rc=%Rrc", rc); /* Test for invalid application. */ RTTESTI_CHECK_RC(RTProcCreateEx("non-existing-app", apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND); /* Test a (hopefully) valid user/password logon (given by parameters of this function). */ RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, pszUser, 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); }
/** * Does a multi-threading list test. Several list additions, reading, replacing * and erasing are done simultaneous. * */ static void test2() { RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); int rc; MTTESTLISTTYPE<MTTESTTYPE> testList; RTTHREAD ahThreads[6]; static PFNRTTHREAD apfnThreads[6] = { MtTest1ThreadProc, MtTest2ThreadProc, MtTest3ThreadProc, MtTest4ThreadProc, MtTest5ThreadProc, MtTest6ThreadProc }; for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) { RTTESTI_CHECK_RC_RETV(RTThreadCreateF(&ahThreads[i], apfnThreads[i], &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest%u", i), VINF_SUCCESS); } uint64_t tsMsDeadline = RTTimeMilliTS() + 60000; for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) { uint64_t tsNow = RTTimeMilliTS(); uint32_t cWait = tsNow > tsMsDeadline ? 5000 : tsMsDeadline - tsNow; RTTESTI_CHECK_RC(RTThreadWait(ahThreads[i], tsNow, NULL), VINF_SUCCESS); } RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); for (size_t i = 0; i < testList.size(); ++i) { uint32_t a = testList.at(i); RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00); } }
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 doStandaloneTests(void) { RTTestISub("Standalone"); PCFGMNODE pRoot;; RTTESTI_CHECK_RETV((pRoot = CFGMR3CreateTree(NULL)) != NULL); doGeneralTests(pRoot); CFGMR3DestroyTree(pRoot); }
/** * Time constrained test with and unlimited N threads. */ static void tst3(uint32_t cThreads, uint32_t cbObject, int iMethod, uint32_t cSecs) { RTTestISubF("Benchmark - %u threads, %u bytes, %u secs, %s", cThreads, cbObject, cSecs, iMethod == 0 ? "RTMemCache" : "RTMemAlloc"); /* * Create a cache with unlimited space, a start semaphore and line up * the threads. */ RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, cbObject, 0 /*cbAlignment*/, UINT32_MAX, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS); RTSEMEVENTMULTI hEvt; RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiCreate(&hEvt)); TST3THREAD aThreads[64]; RTTESTI_CHECK_RETV(cThreads < RT_ELEMENTS(aThreads)); ASMAtomicWriteBool(&g_fTst3Stop, false); for (uint32_t i = 0; i < cThreads; i++) { aThreads[i].hThread = NIL_RTTHREAD; aThreads[i].cIterations = 0; aThreads[i].fUseCache = iMethod == 0; aThreads[i].cbObject = cbObject; aThreads[i].hEvt = hEvt; RTTESTI_CHECK_RC_OK_RETV(RTThreadCreateF(&aThreads[i].hThread, tst3Thread, &aThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst3-%u", i)); } /* * Start the race. */ RTTimeNanoTS(); /* warmup */ uint64_t uStartTS = RTTimeNanoTS(); RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiSignal(hEvt)); RTThreadSleep(cSecs * 1000); ASMAtomicWriteBool(&g_fTst3Stop, true); for (uint32_t i = 0; i < cThreads; i++) RTTESTI_CHECK_RC_OK_RETV(RTThreadWait(aThreads[i].hThread, 60*1000, NULL)); uint64_t cElapsedNS = RTTimeNanoTS() - uStartTS; /* * Sum up the counts. */ uint64_t cIterations = 0; for (uint32_t i = 0; i < cThreads; i++) cIterations += aThreads[i].cIterations; RTTestIPrintf(RTTESTLVL_ALWAYS, "%'8u iterations per second, %'llu ns on avg\n", (unsigned)((long double)cIterations * 1000000000.0 / cElapsedNS), cElapsedNS / cIterations); /* clean up */ RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS); RTTESTI_CHECK_RC_OK(RTSemEventMultiDestroy(hEvt)); }
static void tst1(size_t cTest, size_t cchDigits, char chSep) { RTTestISubF("tst #%u (digits: %u; sep: %c)", cTest, cchDigits, chSep ? chSep : ' '); /* We try to create max possible + one. */ size_t cTimes = 1; for (size_t i = 0; i < cchDigits; ++i) cTimes *= 10; /* Allocate the result array. */ char **papszNames = (char **)RTMemTmpAllocZ(cTimes * sizeof(char *)); RTTESTI_CHECK_RETV(papszNames != NULL); int rc = VERR_INTERNAL_ERROR; /* The test loop. */ size_t i; for (i = 0; i < cTimes; i++) { char szName[RTPATH_MAX]; RTTESTI_CHECK_RC(rc = RTPathAppend(strcpy(szName, g_szTempPath), sizeof(szName), "RTDirCreateUniqueNumbered"), VINF_SUCCESS); if (RT_FAILURE(rc)) break; RTTESTI_CHECK_RC(rc = RTDirCreateUniqueNumbered(szName, sizeof(szName), 0700, cchDigits, chSep), VINF_SUCCESS); if (RT_FAILURE(rc)) { RTTestIFailed("RTDirCreateUniqueNumbered(%s) call #%u -> %Rrc\n", szName, i, rc); break; } RTTESTI_CHECK(papszNames[i] = RTStrDup(szName)); if (!papszNames[i]) break; RTTestIPrintf(RTTESTLVL_DEBUG, "%s\n", papszNames[i]); } /* Try to create one more, which shouldn't be possible. */ if (RT_SUCCESS(rc)) { char szName[RTPATH_MAX]; RTTESTI_CHECK_RC(rc = RTPathAppend(strcpy(szName, g_szTempPath), sizeof(szName), "RTDirCreateUniqueNumbered"), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(rc = RTDirCreateUniqueNumbered(szName, sizeof(szName), 0700, cchDigits, chSep), VERR_ALREADY_EXISTS); } /* cleanup */ while (i-- > 0) { RTTESTI_CHECK_RC(RTDirRemove(papszNames[i]), VINF_SUCCESS); RTStrFree(papszNames[i]); } RTMemTmpFree(papszNames); }
/** * 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 benchmarkFileOpenClose(void) { RTTestSub(g_hTest, "RTFileOpen + RTFileClose"); RTTESTI_CHECK_RC_RETV(benchmarkFileOpenCloseOp(g_szNotExitingFile), VERR_FILE_NOT_FOUND); TIME_OP(benchmarkFileOpenCloseOp(g_szNotExitingFile), "RTFileOpen(g_szNotExitingFile)"); RTTESTI_CHECK_RC_RETV(benchmarkFileOpenCloseOp(g_szNotExitingFile), VERR_FILE_NOT_FOUND); TIME_OP(benchmarkFileOpenCloseOp(g_szNotExitingFile), "RTFileOpen(g_szNotExitingFile)"); int rc = benchmarkFileOpenCloseOp(g_szNotExitingDirFile); RTTESTI_CHECK_RETV(rc == VERR_PATH_NOT_FOUND || VERR_FILE_NOT_FOUND); TIME_OP(benchmarkFileOpenCloseOp(g_szNotExitingDirFile), "RTFileOpen(g_szNotExitingDirFile)"); RTTestSubDone(g_hTest); }
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); }
/** * 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); }
/** * 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); }
/** * Does a multi-threading list test. Several list additions, reading, replacing * and erasing are done simultaneous. * */ static void test2() { RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); RTTHREAD hThread1, hThread2, hThread3, hThread4, hThread5, hThread6; int rc = VINF_SUCCESS; MTTESTLISTTYPE<MTTESTTYPE> testList; rc = RTThreadCreate(&hThread1, &mttest1, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest1"); AssertRC(rc); rc = RTThreadCreate(&hThread2, &mttest2, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest2"); AssertRC(rc); rc = RTThreadCreate(&hThread3, &mttest3, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest3"); AssertRC(rc); rc = RTThreadCreate(&hThread4, &mttest4, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest4"); AssertRC(rc); rc = RTThreadCreate(&hThread5, &mttest5, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest5"); AssertRC(rc); rc = RTThreadCreate(&hThread6, &mttest6, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest6"); AssertRC(rc); rc = RTThreadWait(hThread1, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread2, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread3, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread4, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread5, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread6, RT_INDEFINITE_WAIT, 0); AssertRC(rc); RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); for (size_t i = 0; i < testList.size(); ++i) { uint32_t a = testList.at(i); RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00); } }
static void benchmarkPathQueryInfo(void) { RTTestSub(g_hTest, "RTPathQueryInfo"); RTFSOBJINFO ObjInfo; RTTESTI_CHECK_RC_RETV(RTPathQueryInfo(g_szNotExitingFile, &ObjInfo, RTFSOBJATTRADD_NOTHING), VERR_FILE_NOT_FOUND); TIME_OP(RTPathQueryInfo(g_szNotExitingFile, &ObjInfo, RTFSOBJATTRADD_NOTHING), "RTPathQueryInfo(g_szNotExitingFile)"); int rc = RTPathQueryInfo(g_szNotExitingDirFile, &ObjInfo, RTFSOBJATTRADD_NOTHING); RTTESTI_CHECK_RETV(rc == VERR_PATH_NOT_FOUND || VERR_FILE_NOT_FOUND); TIME_OP(RTPathQueryInfo(g_szNotExitingDirFile, &ObjInfo, RTFSOBJATTRADD_NOTHING), "RTPathQueryInfo(g_szNotExitingDirFile)"); RTTESTI_CHECK_RC_RETV(RTPathQueryInfo(g_pszTestDir, &ObjInfo, RTFSOBJATTRADD_NOTHING), VINF_SUCCESS); TIME_OP(RTPathQueryInfo(g_pszTestDir, &ObjInfo, RTFSOBJATTRADD_NOTHING), "RTPathQueryInfo(g_pszTestDir)"); RTTESTI_CHECK_RC_RETV(RTPathQueryInfo(g_pszTestDir, &ObjInfo, RTFSOBJATTRADD_UNIX), VINF_SUCCESS); TIME_OP(RTPathQueryInfo(g_pszTestDir, &ObjInfo, RTFSOBJATTRADD_UNIX), "RTPathQueryInfo(g_pszTestDir,UNIX)"); RTTestSubDone(g_hTest); }
static void doMemSaferScramble(RTTEST hTest, void *pvBuf, size_t cbAlloc) { /* * Fill it with random bytes and make a reference copy of these. */ RTRandBytes(pvBuf, cbAlloc); void *pvRef = RTMemDup(pvBuf, cbAlloc); RTTESTI_CHECK_RETV(pvRef); /* * Scramble the allocation and check that it no longer matches the refernece bytes. */ int rc = RTMemSaferScramble(pvBuf, cbAlloc); if (RT_SUCCESS(rc)) { if (!memcmp(pvRef, pvBuf, cbAlloc)) RTTestIFailed("Memory blocks must differ (%z bytes, 0x%p vs. 0x%p)!\n", cbAlloc, pvRef, pvBuf); else { /* * Check that unscrambling returns the original content. */ rc = RTMemSaferUnscramble(pvBuf, cbAlloc); if (RT_SUCCESS(rc)) { if (memcmp(pvRef, pvBuf, cbAlloc)) RTTestIFailed("Memory blocks must not differ (%z bytes, 0x%p vs. 0x%p)!\n", cbAlloc, pvRef, pvBuf); } else RTTestIFailed("Unscrambling %z bytes failed with %Rrc!\n", cbAlloc, rc); } } else RTTestIFailed("Scrambling %z bytes failed with %Rrc!\n", cbAlloc, rc); RTMemFree(pvRef); }
static void doInVmmTests(RTTEST hTest) { /* * Create empty VM structure and init SSM. */ int rc = SUPR3Init(NULL); if (RT_FAILURE(rc)) { RTTestSkipped(hTest, "SUPR3Init failed with rc=%Rrc", rc); return; } PVM pVM; RTTESTI_CHECK_RC_RETV(SUPR3PageAlloc(RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT, (void **)&pVM), VINF_SUCCESS); PUVM pUVM = (PUVM)RTMemPageAlloc(sizeof(*pUVM)); pUVM->u32Magic = UVM_MAGIC; pUVM->pVM = pVM; pVM->pUVM = pUVM; /* * Do the testing. */ RTTESTI_CHECK_RC_RETV(STAMR3InitUVM(pUVM), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(MMR3InitUVM(pUVM), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(CFGMR3Init(pVM, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RETV(CFGMR3GetRoot(pVM) != NULL); doTestsOnDefaultValues(CFGMR3GetRoot(pVM)); doGeneralTests(CFGMR3GetRoot(pVM)); /* done */ RTTESTI_CHECK_RC_RETV(CFGMR3Term(pVM), VINF_SUCCESS); }
static void test1(const char *pcszDesc, T3 paTestData[], size_t cTestItems) { RTTestISubF("%s with size of %u (items=%u)", pcszDesc, sizeof(T1), cTestItems); /* * Construction */ /* Create a test list */ L<T1, T2> testList; const size_t defCap = L<T1, T2>::kDefaultCapacity; RTTESTI_CHECK(testList.isEmpty()); RTTESTI_CHECK(testList.size() == 0); RTTESTI_CHECK(testList.capacity() == defCap); /* * Adding */ /* Add the second half of the test data */ size_t cAdded = 1; /* Start adding the second half of our test list */ for (size_t i = cTestItems / 2; i < cTestItems; ++i, ++cAdded) { testList.append(paTestData[i]); RTTESTI_CHECK_RETV(testList.size() == cAdded); RTTESTI_CHECK(testList.at(0) == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList[0] == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList.first() == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[i]); RTTESTI_CHECK(testList[cAdded - 1] == paTestData[i]); RTTESTI_CHECK(testList.last() == paTestData[i]); } /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); RTTESTI_CHECK_RETV(testList.isEmpty() == false); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Start prepending the first half of our test list. Iterate reverse to get * the correct sorting back. */ for (size_t i = cTestItems / 2; i > 0; --i, ++cAdded) { testList.prepend(paTestData[i - 1]); RTTESTI_CHECK_RETV(testList.size() == cAdded); RTTESTI_CHECK(testList.at(0) == paTestData[i - 1]); RTTESTI_CHECK(testList[0] == paTestData[i - 1]); RTTESTI_CHECK(testList.first() == paTestData[i - 1]); RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[cTestItems - 1]); RTTESTI_CHECK(testList[cAdded - 1] == paTestData[cTestItems - 1]); RTTESTI_CHECK(testList.last() == paTestData[cTestItems - 1]); } /* Check that all is correctly prepended. */ RTTESTI_CHECK_RETV(testList.size() == cTestItems); RTTESTI_CHECK_RETV(testList.isEmpty() == false); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[i]); /* * Contains */ L<T1, T2> testList2; /* Check full list. */ RTTESTI_CHECK( testList.contains(paTestData[0])); RTTESTI_CHECK( testList.contains(paTestData[cTestItems / 2])); RTTESTI_CHECK( testList.contains(paTestData[cTestItems - 1])); RTTESTI_CHECK(!testList.contains(T1())); /* Check empty list. */ RTTESTI_CHECK(!testList2.contains(paTestData[0])); RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems / 2])); RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems - 1])); RTTESTI_CHECK(!testList2.contains(T1())); /* * Copy operator */ L<T1, T2> testList3(testList); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i]); /* * "=" operator */ L<T1, T2> testList4; testList4 = testList; /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList4.size() == cTestItems); for (size_t i = 0; i < testList4.size(); ++i) RTTESTI_CHECK(testList4.at(i) == paTestData[i]); /* * Append list */ testList3.append(testList4); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* * Prepend list */ testList3.prepend(testList4); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 3); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* * "value" method */ for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.value(i) == paTestData[i % cTestItems]); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.value(i, T1()) == paTestData[i % cTestItems]); RTTESTI_CHECK(testList3.value(testList3.size() + 1) == T1()); /* Invalid index */ RTTESTI_CHECK(testList3.value(testList3.size() + 1, T1()) == T1()); /* Invalid index */ /* * operator[] (reading) */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[i]); /* * operator[] (writing) * * Replace with inverted array. */ for (size_t i = 0; i < cTestItems; ++i) testList[i] = paTestData[cTestItems - i - 1]; RTTESTI_CHECK_RETV(testList.size() == cTestItems); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[cTestItems - i - 1]); /* * Replace * * Replace with inverted array (Must be original array when finished). */ for (size_t i = 0; i < cTestItems; ++i) testList.replace(i, paTestData[i]); RTTESTI_CHECK_RETV(testList.size() == cTestItems); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[i]); /* * Removing */ /* Remove Range */ testList3.removeRange(cTestItems, cTestItems * 2); RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* Remove the first half (reverse) */ size_t cRemoved = 1; for (size_t i = cTestItems / 2; i > 0; --i, ++cRemoved) { testList.removeAt(i - 1); RTTESTI_CHECK_RETV(testList.size() == cTestItems - cRemoved); } RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); /* Check that all is correctly removed and only the second part of the list * is still there. */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* * setCapacitiy */ testList.setCapacity(cTestItems * 5); RTTESTI_CHECK(testList.capacity() == cTestItems * 5); RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); /* As the capacity just increased, we should still have all entries from * the previous list. */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Decrease the capacity so it will be smaller than the count of items in * the list. The list should be shrink automatically, but the remaining * items should be still valid. */ testList.setCapacity(cTestItems / 4); RTTESTI_CHECK_RETV(testList.size() == cTestItems / 4); RTTESTI_CHECK(testList.capacity() == cTestItems / 4); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Clear all */ testList.clear(); RTTESTI_CHECK_RETV(testList.isEmpty()); RTTESTI_CHECK_RETV(testList.size() == 0); RTTESTI_CHECK(testList.capacity() == defCap); /* Copy empty lists. */ L<T1, T2> testList5(testList); RTTESTI_CHECK_RETV(testList5.isEmpty()); RTTESTI_CHECK_RETV(testList5.size() == 0); RTTESTI_CHECK(testList5.capacity() == 0); testList5.append(paTestData[0]); testList5 = testList; RTTESTI_CHECK_RETV(testList5.isEmpty()); RTTESTI_CHECK_RETV(testList5.size() == 0); RTTESTI_CHECK(testList5.capacity() == 0); /* * Negative testing. */ bool fMayPanic = RTAssertMayPanic(); bool fQuiet = RTAssertAreQuiet(); RTAssertSetMayPanic(false); RTAssertSetQuiet(true); L<T1, T2> testList6; for (size_t i = 0; i < cTestItems; ++i) testList6.insert(i, paTestData[i]); RTTESTI_CHECK(testList6.size() == cTestItems); /* Insertion beyond the end of the array ends up at the end. */ size_t cBefore = testList6.size(); testList6.insert(cBefore + 3, paTestData[0]); RTTESTI_CHECK(testList6.size() == cBefore + 1); RTTESTI_CHECK(testList6.at(cBefore) == paTestData[0]); cBefore = testList6.size(); L<T1, T2> testList7(testList6); testList6.insert(testList6.size() + 42, testList7); RTTESTI_CHECK(testList6.size() == cBefore + testList7.size()); /* Inserting, appending or prepending a list to itself is not supported. */ cBefore = testList6.size(); testList6.insert(3, testList6); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.append(testList6); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.prepend(testList6); RTTESTI_CHECK(testList6.size() == cBefore); /* Replace does nothing if the index is bad. */ cBefore = testList6.size(); testList6.replace(cBefore, testList6[6]); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.replace(cBefore + 64, testList6[6]); RTTESTI_CHECK(testList6.size() == cBefore); /* Indexing beyond the array returns the last element. */ cBefore = testList6.size(); RTTESTI_CHECK(testList6[cBefore] == testList6.last()); RTTESTI_CHECK(testList6[cBefore + 42] == testList6.last()); RTTESTI_CHECK(&testList6[cBefore] == &testList6[cBefore - 1]); RTTESTI_CHECK(&testList6[cBefore + 42] == &testList6[cBefore - 1]); /* removeAt does nothing if the index is bad. */ cBefore = testList6.size(); testList6.removeAt(cBefore); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeAt(cBefore + 42); RTTESTI_CHECK(testList6.size() == cBefore); L<T1, T2> testListEmpty1; RTTESTI_CHECK(!testListEmpty1.size()); testListEmpty1.removeFirst(); RTTESTI_CHECK(!testListEmpty1.size()); testListEmpty1.removeLast(); RTTESTI_CHECK(!testListEmpty1.size()); testListEmpty1.removeAt(128); RTTESTI_CHECK(!testListEmpty1.size()); /* removeRange interprets indexes beyond the end as the end of array (asserted). */ testListEmpty1.removeRange(42, 128); RTTESTI_CHECK(!testListEmpty1.size()); cBefore = testList6.size(); testList6.removeRange(cBefore, cBefore); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeRange(cBefore + 12, cBefore + 128); RTTESTI_CHECK(testList6.size() == cBefore); /* If end is less or equal to the start, nothing is done. */ testListEmpty1.removeRange(128, 0); RTTESTI_CHECK(!testListEmpty1.size()); cBefore = testList6.size(); testList6.removeRange(cBefore, 0); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeRange(0, 0); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeRange(0, 0); RTTESTI_CHECK(testList6.size() == cBefore); RTAssertSetQuiet(fQuiet); RTAssertSetMayPanic(fMayPanic); }
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); }
/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(RTSTRCACHE hStrCache) { const char *psz; /* Simple string entering and length. */ RTTESTI_CHECK_RETV(psz = RTStrCacheEnter(hStrCache, "abcdefgh")); RTTESTI_CHECK_RETV(strcmp(psz, "abcdefgh") == 0); RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("abcdefgh")); RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0); RTTESTI_CHECK_RETV(psz = RTStrCacheEnter(hStrCache, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RETV(strcmp(psz, "abcdefghijklmnopqrstuvwxyz") == 0); RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0); /* Unterminated strings. */ RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, "0123456789", 3)); RTTESTI_CHECK_RETV(strcmp(psz, "012") == 0); RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("012")); RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0); RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, "0123456789abcdefghijklmnopqrstuvwxyz", 16)); RTTESTI_CHECK_RETV(strcmp(psz, "0123456789abcdef") == 0); RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("0123456789abcdef")); RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0); /* String referencing. */ char szTest[4096+16]; memset(szTest, 'a', sizeof(szTest)); char szTest2[4096+16]; memset(szTest2, 'f', sizeof(szTest)); for (int32_t i = 4096; i > 3; i /= 3) { void *pv2; RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, szTest, i)); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz)); RTTESTI_CHECK(RTStrCacheRetain(psz) == 2); RTTESTI_CHECK(RTStrCacheRetain(psz) == 3); RTTESTI_CHECK(RTStrCacheRetain(psz) == 4); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz)); RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 3); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz)); RTTESTI_CHECK(RTStrCacheRetain(psz) == 4); RTTESTI_CHECK(RTStrCacheRetain(psz) == 5); RTTESTI_CHECK(RTStrCacheRetain(psz) == 6); RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 5); RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 4); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz)); for (uint32_t cRefs = 3;; cRefs--) { RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == cRefs); if (cRefs == 0) break; RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x cRefs=%d\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz, cRefs)); for (uint32_t j = 0; j < 42; j++) { const char *psz2; RTTESTI_CHECK_RETV(psz2 = RTStrCacheEnterN(hStrCache, szTest2, i)); RTTESTI_CHECK_RETV(psz2 != psz); RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz2) == 0); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x cRefs=%d\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz, cRefs)); } } } /* Lots of allocations. */ memset(szTest, 'b', sizeof(szTest)); memset(szTest2, 'e', sizeof(szTest)); const char *pszTest1Rets[4096 + 16]; const char *pszTest2Rets[4096 + 16]; for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++) { RTTESTI_CHECK(pszTest1Rets[i] = RTStrCacheEnterN(hStrCache, szTest, i)); RTTESTI_CHECK(strlen(pszTest1Rets[i]) == i); RTTESTI_CHECK(pszTest2Rets[i] = RTStrCacheEnterN(hStrCache, szTest2, i)); RTTESTI_CHECK(strlen(pszTest2Rets[i]) == i); } if (RTStrCacheIsRealImpl()) { for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++) { uint32_t cRefs; const char *psz1, *psz2; RTTESTI_CHECK((psz1 = RTStrCacheEnterN(hStrCache, szTest, i)) == pszTest1Rets[i]); RTTESTI_CHECK((psz2 = RTStrCacheEnterN(hStrCache, szTest2, i)) == pszTest2Rets[i]); RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, psz1)) == 1, ("cRefs=%#x i=%#x\n", cRefs, i)); RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, psz2)) == 1, ("cRefs=%#x i=%#x\n", cRefs, i)); } } for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++) { uint32_t cRefs; RTTESTI_CHECK(strlen(pszTest1Rets[i]) == i); RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, pszTest1Rets[i])) == 0, ("cRefs=%#x i=%#x\n", cRefs, i)); RTTESTI_CHECK(strlen(pszTest2Rets[i]) == i); RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, pszTest2Rets[i])) == 0, ("cRefs=%#x i=%#x\n", cRefs, i)); } }
static void doTest(RTTEST hTest) { NOREF(hTest); uint32_t iAllocCpu = 0; while (iAllocCpu < RTCPUSET_MAX_CPUS) { const uint32_t cbTestSet = _1M * 32; const uint32_t cIterations = 384; /* * Change CPU and allocate a chunk of memory. */ RTTESTI_CHECK_RC_OK_RETV(RTThreadSetAffinityToCpu(RTMpCpuIdFromSetIndex(iAllocCpu))); void *pvTest = RTMemPageAlloc(cbTestSet); /* may be leaked, who cares */ RTTESTI_CHECK_RETV(pvTest != NULL); memset(pvTest, 0xef, cbTestSet); /* * Do the tests. */ uint32_t iAccessCpu = 0; while (iAccessCpu < RTCPUSET_MAX_CPUS) { RTTESTI_CHECK_RC_OK_RETV(RTThreadSetAffinityToCpu(RTMpCpuIdFromSetIndex(iAccessCpu))); /* * The write test. */ RTTimeNanoTS(); RTThreadYield(); uint64_t u64StartTS = RTTimeNanoTS(); for (uint32_t i = 0; i < cIterations; i++) { ASMCompilerBarrier(); /* paranoia */ memset(pvTest, i, cbTestSet); } uint64_t const cNsElapsedWrite = RTTimeNanoTS() - u64StartTS; uint64_t cMBPerSec = (uint64_t)( ((uint64_t)cIterations * cbTestSet) /* bytes */ / ((long double)cNsElapsedWrite / RT_NS_1SEC_64) /* seconds */ / _1M /* MB */ ); RTTestIValueF(cMBPerSec, RTTESTUNIT_MEGABYTES_PER_SEC, "cpu%02u-mem%02u-write", iAllocCpu, iAccessCpu); /* * The read test. */ memset(pvTest, 0, cbTestSet); RTTimeNanoTS(); RTThreadYield(); u64StartTS = RTTimeNanoTS(); for (uint32_t i = 0; i < cIterations; i++) { #if 1 size_t register u = 0; size_t volatile *puCur = (size_t volatile *)pvTest; size_t volatile *puEnd = puCur + cbTestSet / sizeof(size_t); while (puCur != puEnd) u += *puCur++; #else ASMCompilerBarrier(); /* paranoia */ void *pvFound = memchr(pvTest, (i & 127) + 1, cbTestSet); RTTESTI_CHECK(pvFound == NULL); #endif } uint64_t const cNsElapsedRead = RTTimeNanoTS() - u64StartTS; cMBPerSec = (uint64_t)( ((uint64_t)cIterations * cbTestSet) /* bytes */ / ((long double)cNsElapsedRead / RT_NS_1SEC_64) /* seconds */ / _1M /* MB */ ); RTTestIValueF(cMBPerSec, RTTESTUNIT_MEGABYTES_PER_SEC, "cpu%02u-mem%02u-read", iAllocCpu, iAccessCpu); /* * The read/write test. */ RTTimeNanoTS(); RTThreadYield(); u64StartTS = RTTimeNanoTS(); for (uint32_t i = 0; i < cIterations; i++) { ASMCompilerBarrier(); /* paranoia */ memcpy(pvTest, (uint8_t *)pvTest + cbTestSet / 2, cbTestSet / 2); } uint64_t const cNsElapsedRW = RTTimeNanoTS() - u64StartTS; cMBPerSec = (uint64_t)( ((uint64_t)cIterations * cbTestSet) /* bytes */ / ((long double)cNsElapsedRW / RT_NS_1SEC_64) /* seconds */ / _1M /* MB */ ); RTTestIValueF(cMBPerSec, RTTESTUNIT_MEGABYTES_PER_SEC, "cpu%02u-mem%02u-read-write", iAllocCpu, iAccessCpu); /* * Total time. */ RTTestIValueF(cNsElapsedRead + cNsElapsedWrite + cNsElapsedRW, RTTESTUNIT_NS, "cpu%02u-mem%02u-time", iAllocCpu, iAccessCpu); /* advance */ iAccessCpu = getNextCpu(iAccessCpu); } /* * Clean up and advance to the next CPU. */ RTMemPageFree(pvTest, cbTestSet); iAllocCpu = getNextCpu(iAllocCpu); } }
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); }
/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(RTMEMPOOL hMemPool) { void *pv; /* Normal alloc. */ RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 1)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 0)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); /* Zeroed allocation. */ for (uint32_t i = 0; i < 512; i++) { RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 1024)); RTTESTI_CHECK(ASMMemFirstMismatchingU32(pv, 1024, 0) == NULL); memset(pv, 'a', 1024); RTTESTI_CHECK_RETV(RTMemPoolRefCount(pv) == 1); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); } RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 0)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); /* Duped allocation. */ static const char szTest[] = "test string abcdef"; RTTESTI_CHECK_RETV(pv = RTMemPoolDup(hMemPool, szTest, sizeof(szTest))); RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); for (uint32_t i = 0; i < 512; i++) { size_t const cb = 256 - sizeof(szTest); RTTESTI_CHECK_RETV(pv = RTMemPoolDupEx(hMemPool, szTest, sizeof(szTest), cb)); RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0); RTTESTI_CHECK(ASMMemIsZero((uint8_t *)pv + sizeof(szTest), cb)); memset(pv, 'b', sizeof(szTest) + cb); RTTESTI_CHECK_RETV(RTMemPoolRefCount(pv) == 1); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); } /* Reallocation */ RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 1)); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 2)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 42)); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 32)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 128)); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 256)); RTTESTI_CHECK_RETV(RTMemPoolRealloc(hMemPool, pv, 0) == NULL); /* Free (a bit hard to test) */ RTMemPoolFree(hMemPool, NULL); RTMemPoolFree(hMemPool, RTMemPoolAlloc(hMemPool, 42)); /* Memory referencing. */ for (uint32_t i = 1; i <= 4096; i *= 3) { void *pv2; RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, i)); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 1); memset(pv, 'a', i); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv,(uintptr_t)pv2 - (uintptr_t)pv)); RTTESTI_CHECK(RTMemPoolRetain(pv) == 2); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 2); RTTESTI_CHECK(RTMemPoolRetain(pv) == 3); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 3); RTTESTI_CHECK(RTMemPoolRetain(pv) == 4); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 4); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == 3); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 3); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); RTTESTI_CHECK(RTMemPoolRetain(pv) == 4); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 4); RTTESTI_CHECK(RTMemPoolRetain(pv) == 5); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 5); RTTESTI_CHECK(RTMemPoolRetain(pv) == 6); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 6); RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 5); RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 4); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); for (uint32_t cRefs = 3;; cRefs--) { RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == cRefs); if (cRefs == 0) break; RTTESTI_CHECK(RTMemPoolRefCount(pv) == cRefs); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs)); for (uint32_t j = 0; j < 42; j++) { RTTESTI_CHECK_RETV(pv2 = RTMemPoolAlloc(hMemPool, i)); RTTESTI_CHECK_RETV(pv2 != pv); memset(pv2, 'f', i); RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv2) == 0); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs)); } } } }
void tstFileAioTestReadWriteBasic(RTFILE File, bool fWrite, void *pvTestBuf, size_t cbTestBuf, size_t cbTestFile, uint32_t cMaxReqsInFlight) { /* Allocate request array. */ RTFILEAIOREQ *paReqs; paReqs = (PRTFILEAIOREQ)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(RTFILEAIOREQ)); RTTESTI_CHECK_RETV(paReqs); RT_BZERO(paReqs, sizeof(cMaxReqsInFlight * sizeof(RTFILEAIOREQ))); /* Allocate array holding pointer to data buffers. */ void **papvBuf = (void **)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(void *)); RTTESTI_CHECK_RETV(papvBuf); /* Allocate the buffers*/ for (unsigned i = 0; i < cMaxReqsInFlight; i++) { RTTESTI_CHECK_RC_OK_RETV(RTTestGuardedAlloc(g_hTest, cbTestBuf, PAGE_SIZE, true /*fHead*/, &papvBuf[i])); if (fWrite) memcpy(papvBuf[i], pvTestBuf, cbTestBuf); if (fWrite) memcpy(papvBuf[i], pvTestBuf, cbTestBuf); else RT_BZERO(papvBuf[i], cbTestBuf); } /* Allocate array holding completed requests. */ RTFILEAIOREQ *paReqsCompleted; paReqsCompleted = (PRTFILEAIOREQ)RTTestGuardedAllocHead(g_hTest, cMaxReqsInFlight * sizeof(RTFILEAIOREQ)); RTTESTI_CHECK_RETV(paReqsCompleted); RT_BZERO(paReqsCompleted, cMaxReqsInFlight * sizeof(RTFILEAIOREQ)); /* Create a context and associate the file handle with it. */ RTFILEAIOCTX hAioContext; RTTESTI_CHECK_RC_RETV(RTFileAioCtxCreate(&hAioContext, cMaxReqsInFlight, 0 /* fFlags */), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTFileAioCtxAssociateWithFile(hAioContext, File), VINF_SUCCESS); /* Initialize requests. */ for (unsigned i = 0; i < cMaxReqsInFlight; i++) RTFileAioReqCreate(&paReqs[i]); RTFOFF off = 0; int cRuns = 0; uint64_t NanoTS = RTTimeNanoTS(); size_t cbLeft = cbTestFile; while (cbLeft) { int rc; int cReqs = 0; for (unsigned i = 0; i < cMaxReqsInFlight; i++) { size_t cbTransfer = cbLeft < cbTestBuf ? cbLeft : cbTestBuf; if (!cbTransfer) break; if (fWrite) rc = RTFileAioReqPrepareWrite(paReqs[i], File, off, papvBuf[i], cbTransfer, papvBuf[i]); else rc = RTFileAioReqPrepareRead(paReqs[i], File, off, papvBuf[i], cbTransfer, papvBuf[i]); RTTESTI_CHECK_RC(rc, VINF_SUCCESS); cbLeft -= cbTransfer; off += cbTransfer; cReqs++; } rc = RTFileAioCtxSubmit(hAioContext, paReqs, cReqs); RTTESTI_CHECK_MSG(rc == VINF_SUCCESS, ("Failed to submit tasks after %d runs. rc=%Rrc\n", cRuns, rc)); if (rc != VINF_SUCCESS) break; /* Wait */ uint32_t cCompleted = 0; RTTESTI_CHECK_RC(rc = RTFileAioCtxWait(hAioContext, cReqs, RT_INDEFINITE_WAIT, paReqsCompleted, cMaxReqsInFlight, &cCompleted), VINF_SUCCESS); if (rc != VINF_SUCCESS) break; if (!fWrite) { for (uint32_t i = 0; i < cCompleted; i++) { /* Compare that we read the right stuff. */ void *pvBuf = RTFileAioReqGetUser(paReqsCompleted[i]); RTTESTI_CHECK(pvBuf); size_t cbTransfered; RTTESTI_CHECK_RC(rc = RTFileAioReqGetRC(paReqsCompleted[i], &cbTransfered), VINF_SUCCESS); if (rc != VINF_SUCCESS) break; RTTESTI_CHECK_MSG(cbTransfered == cbTestBuf, ("cbTransfered=%zd\n", cbTransfered)); RTTESTI_CHECK_RC_OK(rc = (memcmp(pvBuf, pvTestBuf, cbTestBuf) == 0 ? VINF_SUCCESS : VERR_BAD_EXE_FORMAT)); if (rc != VINF_SUCCESS) break; memset(pvBuf, 0, cbTestBuf); } } cRuns++; if (RT_FAILURE(rc)) break; } NanoTS = RTTimeNanoTS() - NanoTS; uint64_t SpeedKBs = (uint64_t)(cbTestFile / (NanoTS / 1000000000.0) / 1024); RTTestValue(g_hTest, "Throughput", SpeedKBs, RTTESTUNIT_KILOBYTES_PER_SEC); /* cleanup */ for (unsigned i = 0; i < cMaxReqsInFlight; i++) RTTestGuardedFree(g_hTest, papvBuf[i]); RTTestGuardedFree(g_hTest, papvBuf); for (unsigned i = 0; i < cMaxReqsInFlight; i++) RTTESTI_CHECK_RC(RTFileAioReqDestroy(paReqs[i]), VINF_SUCCESS); RTTESTI_CHECK_RC(RTFileAioCtxDestroy(hAioContext), VINF_SUCCESS); RTTestGuardedFree(g_hTest, paReqs); }
static void tstObjectCreateTemp(const char *pszSubTest, const char *pszTemplate, bool fFile, RTFMODE fMode, unsigned cTimes, bool fSkipXCheck) { RTTestISub(pszSubTest); const char *pcszAPI = fFile ? "RTFileCreateTemp" : "RTDirCreateTemp"; /* 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]; RTFMODE fModeFinal; 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 = fFile ? RTFileCreateTemp(papszNames[i], fMode) : RTDirCreateTemp(papszNames[i], fMode); if (rc != VINF_SUCCESS) { RTTestIFailed("%s(%s, %#o) call #%u -> %Rrc\n", pcszAPI, szName, (int)fMode, i, rc); RTStrFree(papszNames[i]); papszNames[i] = NULL; break; } /* Check that the final permissions are not more permissive than * the ones requested (less permissive is fine, c.f. umask etc.). * I mask out the group as I am not sure how we deal with that on * Windows. */ RTTESTI_CHECK_RC_OK(rc = RTPathGetMode(papszNames[i], &fModeFinal)); if (RT_SUCCESS(rc)) { fModeFinal &= (RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXO); RTTESTI_CHECK_MSG((fModeFinal & ~fMode) == 0, ("%s: szName %s\nfModeFinal ~= %#o, expected %#o\n", pcszAPI, szName, fModeFinal, (int)fMode)); } RTTestIPrintf(RTTESTLVL_DEBUG, "%s: %s\n", pcszAPI, papszNames[i]); RTTESTI_CHECK_MSG(strlen(szName) == strlen(papszNames[i]), ("%s: szName %s\nReturned %s\n", pcszAPI, szName, papszNames[i])); if (!fSkipXCheck) RTTESTI_CHECK_MSG(strchr(RTPathFilename(papszNames[i]), 'X') == NULL, ("%s: szName %s\nReturned %s\n", pcszAPI, szName, papszNames[i])); } /* cleanup */ while (i-- > 0) { if (fFile) RTTESTI_CHECK_RC(RTFileDelete(papszNames[i]), VINF_SUCCESS); else RTTESTI_CHECK_RC(RTDirRemove(papszNames[i]), VINF_SUCCESS); RTStrFree(papszNames[i]); } RTMemTmpFree(papszNames); }
static void test1(RTTEST hTest) { RTTestSub(hTest, "Basics"); #define CHECK(expr) RTTESTI_CHECK(expr) #define CHECK_DUMP(expr, value) \ do { \ if (!(expr)) \ RTTestFailed(hTest, "%d: FAILED %s, got \"%s\"", __LINE__, #expr, value); \ } while (0) #define CHECK_DUMP_I(expr) \ do { \ if (!(expr)) \ RTTestFailed(hTest, "%d: FAILED %s, got \"%d\"", __LINE__, #expr, expr); \ } while (0) #define CHECK_EQUAL(Str, szExpect) \ do { \ if (!(Str).equals(szExpect)) \ RTTestIFailed("line %u: expected \"%s\" got \"%s\"", __LINE__, szExpect, (Str).c_str()); \ } while (0) #define CHECK_EQUAL_I(iRes, iExpect) \ do { \ if (iRes != iExpect) \ RTTestIFailed("line %u: expected \"%zd\" got \"%zd\"", __LINE__, iExpect, iRes); \ } while (0) RTCString empty; CHECK(empty.length() == 0); CHECK(empty.capacity() == 0); RTCString sixbytes("12345"); CHECK(sixbytes.length() == 5); CHECK(sixbytes.capacity() == 6); sixbytes.append(RTCString("678")); CHECK(sixbytes.length() == 8); CHECK(sixbytes.capacity() >= 9); sixbytes.append("9a"); CHECK(sixbytes.length() == 10); CHECK(sixbytes.capacity() >= 11); char *psz = sixbytes.mutableRaw(); // 123456789a // ^ // 0123456 psz[6] = '\0'; sixbytes.jolt(); CHECK(sixbytes.length() == 6); CHECK(sixbytes.capacity() == 7); RTCString morebytes("tobereplaced"); morebytes = "newstring "; morebytes.append(sixbytes); CHECK_DUMP(morebytes == "newstring 123456", morebytes.c_str()); RTCString third(morebytes); third.reserve(100 * 1024); // 100 KB CHECK_DUMP(third == "newstring 123456", morebytes.c_str() ); CHECK(third.capacity() == 100 * 1024); CHECK(third.length() == morebytes.length()); // must not have changed RTCString copy1(morebytes); RTCString copy2 = morebytes; CHECK(copy1 == copy2); copy1 = NULL; CHECK(copy1.length() == 0); copy1 = ""; CHECK(copy1.length() == 0); CHECK(RTCString("abc") < RTCString("def")); CHECK(RTCString("") < RTCString("def")); CHECK(RTCString("abc") > RTCString("")); CHECK(RTCString("abc") != RTCString("def")); CHECK_DUMP_I(RTCString("def") > RTCString("abc")); CHECK(RTCString("abc") == RTCString("abc")); CHECK(RTCString("").compare("") == 0); CHECK(RTCString("").compare(NULL) == 0); CHECK(RTCString("").compare("a") < 0); CHECK(RTCString("a").compare("") > 0); CHECK(RTCString("a").compare(NULL) > 0); CHECK(RTCString("abc") < "def"); CHECK(RTCString("abc") != "def"); CHECK_DUMP_I(RTCString("def") > "abc"); CHECK(RTCString("abc") == "abc"); CHECK(RTCString("abc").equals("abc")); CHECK(!RTCString("abc").equals("def")); CHECK(RTCString("abc").equalsIgnoreCase("Abc")); CHECK(RTCString("abc").equalsIgnoreCase("ABc")); CHECK(RTCString("abc").equalsIgnoreCase("ABC")); CHECK(!RTCString("abc").equalsIgnoreCase("dBC")); CHECK(RTCString("").equals("")); CHECK(RTCString("").equals(NULL)); CHECK(!RTCString("").equals("a")); CHECK(!RTCString("a").equals("")); CHECK(!RTCString("a").equals(NULL)); CHECK(RTCString("").equalsIgnoreCase("")); CHECK(RTCString("").equalsIgnoreCase(NULL)); CHECK(!RTCString("").equalsIgnoreCase("a")); CHECK(!RTCString("a").equalsIgnoreCase("")); copy2.setNull(); for (int i = 0; i < 100; ++i) { copy2.reserve(50); // should be ignored after 50 loops copy2.append("1"); } CHECK(copy2.length() == 100); copy2.setNull(); for (int i = 0; i < 100; ++i) { copy2.reserve(50); // should be ignored after 50 loops copy2.append('1'); } CHECK(copy2.length() == 100); /* printf */ RTCString StrFmt; CHECK(StrFmt.printf("%s-%s-%d", "abc", "def", 42).equals("abc-def-42")); test1Hlp1("abc-42-def", "%s-%d-%s", "abc", 42, "def"); test1Hlp1("", ""); test1Hlp1("1", "1"); test1Hlp1("foobar", "%s", "foobar"); /* substring constructors */ RTCString SubStr1("", (size_t)0); CHECK_EQUAL(SubStr1, ""); RTCString SubStr2("abcdef", 2); CHECK_EQUAL(SubStr2, "ab"); RTCString SubStr3("abcdef", 1); CHECK_EQUAL(SubStr3, "a"); RTCString SubStr4("abcdef", 6); CHECK_EQUAL(SubStr4, "abcdef"); RTCString SubStr5("abcdef", 7); CHECK_EQUAL(SubStr5, "abcdef"); RTCString SubStrBase("abcdef"); RTCString SubStr10(SubStrBase, 0); CHECK_EQUAL(SubStr10, "abcdef"); RTCString SubStr11(SubStrBase, 1); CHECK_EQUAL(SubStr11, "bcdef"); RTCString SubStr12(SubStrBase, 1, 1); CHECK_EQUAL(SubStr12, "b"); RTCString SubStr13(SubStrBase, 2, 3); CHECK_EQUAL(SubStr13, "cde"); RTCString SubStr14(SubStrBase, 2, 4); CHECK_EQUAL(SubStr14, "cdef"); RTCString SubStr15(SubStrBase, 2, 5); CHECK_EQUAL(SubStr15, "cdef"); /* substr() and substrCP() functions */ RTCString strTest(""); CHECK_EQUAL(strTest.substr(0), ""); CHECK_EQUAL(strTest.substrCP(0), ""); CHECK_EQUAL(strTest.substr(1), ""); CHECK_EQUAL(strTest.substrCP(1), ""); /* now let's have some non-ASCII to chew on */ strTest = "abcdefßäbcdef"; // 13 codepoints, but 15 bytes (excluding null terminator); // "ß" and "ä" consume two bytes each CHECK_EQUAL(strTest.substr(0), strTest.c_str()); CHECK_EQUAL(strTest.substrCP(0), strTest.c_str()); CHECK_EQUAL(strTest.substr(2), "cdefßäbcdef"); CHECK_EQUAL(strTest.substrCP(2), "cdefßäbcdef"); CHECK_EQUAL(strTest.substr(2, 2), "cd"); CHECK_EQUAL(strTest.substrCP(2, 2), "cd"); CHECK_EQUAL(strTest.substr(6), "ßäbcdef"); CHECK_EQUAL(strTest.substrCP(6), "ßäbcdef"); CHECK_EQUAL(strTest.substr(6, 2), "ß"); // UTF-8 "ß" consumes two bytes CHECK_EQUAL(strTest.substrCP(6, 1), "ß"); CHECK_EQUAL(strTest.substr(8), "äbcdef"); // UTF-8 "ß" consumes two bytes CHECK_EQUAL(strTest.substrCP(7), "äbcdef"); CHECK_EQUAL(strTest.substr(8, 3), "äb"); // UTF-8 "ä" consumes two bytes CHECK_EQUAL(strTest.substrCP(7, 2), "äb"); CHECK_EQUAL(strTest.substr(14, 1), "f"); CHECK_EQUAL(strTest.substrCP(12, 1), "f"); CHECK_EQUAL(strTest.substr(15, 1), ""); CHECK_EQUAL(strTest.substrCP(13, 1), ""); CHECK_EQUAL(strTest.substr(16, 1), ""); CHECK_EQUAL(strTest.substrCP(15, 1), ""); /* and check cooperation with find() */ size_t pos = strTest.find("ß"); CHECK_EQUAL(strTest.substr(pos), "ßäbcdef"); /* check find() */ CHECK_EQUAL_I(strTest.find("f"), 5); CHECK_EQUAL_I(strTest.find("f", 0), 5); CHECK_EQUAL_I(strTest.find("f", 3), 5); CHECK_EQUAL_I(strTest.find("f", 6), 14); CHECK_EQUAL_I(strTest.find("f", 9), 14); CHECK_EQUAL_I(strTest.substr(pos).find("d"), 6); /* split */ RTCList<RTCString> spList1 = RTCString("##abcdef##abcdef####abcdef##").split("##", RTCString::RemoveEmptyParts); RTTESTI_CHECK(spList1.size() == 3); for (size_t i = 0; i < spList1.size(); ++i) RTTESTI_CHECK(spList1.at(i) == "abcdef"); RTCList<RTCString> spList2 = RTCString("##abcdef##abcdef####abcdef##").split("##", RTCString::KeepEmptyParts); RTTESTI_CHECK_RETV(spList2.size() == 5); RTTESTI_CHECK(spList2.at(0) == ""); RTTESTI_CHECK(spList2.at(1) == "abcdef"); RTTESTI_CHECK(spList2.at(2) == "abcdef"); RTTESTI_CHECK(spList2.at(3) == ""); RTTESTI_CHECK(spList2.at(4) == "abcdef"); RTCList<RTCString> spList3 = RTCString().split("##", RTCString::KeepEmptyParts); RTTESTI_CHECK(spList3.size() == 0); RTCList<RTCString> spList4 = RTCString().split(""); RTTESTI_CHECK(spList4.size() == 0); RTCList<RTCString> spList5 = RTCString("abcdef").split(""); RTTESTI_CHECK_RETV(spList5.size() == 1); RTTESTI_CHECK(spList5.at(0) == "abcdef"); /* join */ RTCList<RTCString> jnList; strTest = RTCString::join(jnList); RTTESTI_CHECK(strTest == ""); strTest = RTCString::join(jnList, "##"); RTTESTI_CHECK(strTest == ""); jnList.append("abcdef"); strTest = RTCString::join(jnList, "##"); RTTESTI_CHECK(strTest == "abcdef"); jnList.append("abcdef"); strTest = RTCString::join(jnList, ";"); RTTESTI_CHECK(strTest == "abcdef;abcdef"); for (size_t i = 0; i < 3; ++i) jnList.append("abcdef"); strTest = RTCString::join(jnList); RTTESTI_CHECK(strTest == "abcdefabcdefabcdefabcdefabcdef"); strTest = RTCString::join(jnList, "##"); RTTESTI_CHECK(strTest == "abcdef##abcdef##abcdef##abcdef##abcdef"); /* special constructor and assignment arguments */ RTCString StrCtor1(""); RTTESTI_CHECK(StrCtor1.isEmpty()); RTTESTI_CHECK(StrCtor1.length() == 0); RTCString StrCtor2(NULL); RTTESTI_CHECK(StrCtor2.isEmpty()); RTTESTI_CHECK(StrCtor2.length() == 0); RTCString StrCtor1d(StrCtor1); RTTESTI_CHECK(StrCtor1d.isEmpty()); RTTESTI_CHECK(StrCtor1d.length() == 0); RTCString StrCtor2d(StrCtor2); RTTESTI_CHECK(StrCtor2d.isEmpty()); RTTESTI_CHECK(StrCtor2d.length() == 0); for (unsigned i = 0; i < 2; i++) { RTCString StrAssign; if (i) StrAssign = "abcdef"; StrAssign = (char *)NULL; RTTESTI_CHECK(StrAssign.isEmpty()); RTTESTI_CHECK(StrAssign.length() == 0); if (i) StrAssign = "abcdef"; StrAssign = ""; RTTESTI_CHECK(StrAssign.isEmpty()); RTTESTI_CHECK(StrAssign.length() == 0); if (i) StrAssign = "abcdef"; StrAssign = StrCtor1; RTTESTI_CHECK(StrAssign.isEmpty()); RTTESTI_CHECK(StrAssign.length() == 0); if (i) StrAssign = "abcdef"; StrAssign = StrCtor2; RTTESTI_CHECK(StrAssign.isEmpty()); RTTESTI_CHECK(StrAssign.length() == 0); } #undef CHECK #undef CHECK_DUMP #undef CHECK_DUMP_I #undef CHECK_EQUAL }