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 testCheckDeviceRoot(RTTEST hTest) { RTTestSub(hTest, "Testing the USBProxyLinuxCheckDeviceRoot API"); for (unsigned i = 0; i < RT_ELEMENTS(s_testCheckDeviceRoot); ++i) { TestUSBSetAvailableUsbfsDevices(s_testCheckDeviceRoot[i] .pacszDeviceAddresses); TestUSBSetAccessibleFiles(s_testCheckDeviceRoot[i] .pacszAccessibleFiles); bool fAvailable = USBProxyLinuxCheckDeviceRoot (s_testCheckDeviceRoot[i].pcszRoot, s_testCheckDeviceRoot[i].fIsDeviceNodes); RTTESTI_CHECK_MSG( fAvailable == s_testCheckDeviceRoot[i].fAvailableExpected, ("USBProxyLinuxCheckDeviceRoot() returned %RTbool (test index %i) instead of %RTbool!\n", fAvailable, i, s_testCheckDeviceRoot[i].fAvailableExpected)); } }
void tst(int iFrom, int iTo, int iInc) { #ifdef VMM_R0_SWITCH_STACK int const cIterations = iFrom > iTo ? iFrom - iTo : iTo - iFrom; void *pvPrev = alloca(1); #endif RTR0PTR R0PtrSaved = g_Jmp.pvSavedStack; RT_ZERO(g_Jmp); g_Jmp.pvSavedStack = R0PtrSaved; memset((void *)g_Jmp.pvSavedStack, '\0', VMM_STACK_SIZE); g_cbFoo = 0; g_cJmps = 0; g_cbFooUsed = 0; for (int i = iFrom, iItr = 0; i != iTo; i += iInc, iItr++) { int rc = vmmR0CallRing3SetJmp(&g_Jmp, (PFNVMMR0SETJMP)tst2, (PVM)i, 0); RTTESTI_CHECK_MSG_RETV(rc == 0 || rc == 42, ("i=%d rc=%d setjmp; cbFoo=%#x cbFooUsed=%#x\n", i, rc, g_cbFoo, g_cbFooUsed)); #ifdef VMM_R0_SWITCH_STACK /* Make the stack pointer slide for the second half of the calls. */ if (iItr >= cIterations / 2) { /* Note! gcc does funny rounding up of alloca(). */ void *pv2 = alloca((i % 63) | 1); size_t cb2 = (uintptr_t)pvPrev - (uintptr_t)pv2; RTTESTI_CHECK_MSG(cb2 >= 16 && cb2 <= 128, ("cb2=%zu pv2=%p pvPrev=%p iAlloca=%d\n", cb2, pv2, pvPrev, iItr)); memset(pv2, 0xff, cb2); memset(pvPrev, 0xee, 1); pvPrev = pv2; } #endif } RTTESTI_CHECK_MSG_RETV(g_cJmps, ("No jumps!")); if (g_Jmp.cbUsedAvg || g_Jmp.cUsedTotal) RTTestIPrintf(RTTESTLVL_ALWAYS, "cbUsedAvg=%#x cbUsedMax=%#x cUsedTotal=%#llx\n", g_Jmp.cbUsedAvg, g_Jmp.cbUsedMax, g_Jmp.cUsedTotal); }
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 tstQueryInformationProcess(void) { RTTestISub("NtQueryInformationProcess"); NTSTATUS rcNt; /* Basic info */ PROCESS_BASIC_INFORMATION BasicInfo; RT_ZERO(BasicInfo); DWORD cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), &cbActual); RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt)); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "BasicInfo:\n" " UniqueProcessId = %#x (%6d)\n" " InheritedFromUniqueProcessId = %#x (%6d)\n" " ExitStatus = %#x\n" " PebBaseAddress = %p\n" " AffinityMask = %#zx\n" " BasePriority = %#zx\n" , BasicInfo.UniqueProcessId, BasicInfo.UniqueProcessId, BasicInfo.InheritedFromUniqueProcessId, BasicInfo.InheritedFromUniqueProcessId, BasicInfo.ExitStatus, BasicInfo.PebBaseAddress, BasicInfo.AffinityMask, BasicInfo.BasePriority ); /* Debugger present? */ DWORD_PTR uPtr = ~(DWORD_PTR)0; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessDebugPort, &uPtr, sizeof(uPtr), &cbActual); RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt)); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessDebugPort: %p\n", uPtr); /* Debug object handle, whatever that is... */ uPtr = ~(DWORD_PTR)0; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessDebugObjectHandle, &uPtr, sizeof(uPtr), &cbActual); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessDebugObjectHandle: %p\n", uPtr); else if (rcNt == STATUS_PORT_NOT_SET) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessDebugObjectHandle: rcNt=%#x (STATUS_PORT_NOT_SET)\n", uPtr); else RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt)); /* 32-bit app on 64-bit host? */ uPtr = ~(DWORD_PTR)0; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessWow64Information, &uPtr, sizeof(uPtr), &cbActual); RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt)); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessWow64Information: %p\n", uPtr); /* Process image name (NT). */ struct { UNICODE_STRING UniStr; WCHAR awBuffer[UNICODE_STRING_MAX_CHARS]; } StrBuf; RT_ZERO(StrBuf); StrBuf.UniStr.Length = UNICODE_STRING_MAX_CHARS * 2; StrBuf.UniStr.MaximumLength = UNICODE_STRING_MAX_CHARS * 2; StrBuf.UniStr.Buffer = &StrBuf.awBuffer[0]; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessImageFileName, &StrBuf, sizeof(StrBuf), &cbActual); RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt)); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileName: len=%u\n %.*ls\n", StrBuf.UniStr.Length, StrBuf.UniStr.Length, StrBuf.UniStr.Buffer); /* Process image name (Win32) - Not available on Windows 2003. */ RT_ZERO(StrBuf); StrBuf.UniStr.Length = UNICODE_STRING_MAX_CHARS * 2; StrBuf.UniStr.MaximumLength = UNICODE_STRING_MAX_CHARS * 2; StrBuf.UniStr.Buffer = &StrBuf.awBuffer[0]; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessImageFileNameWin32, &StrBuf, sizeof(StrBuf), &cbActual); if (rcNt != STATUS_INVALID_INFO_CLASS) { RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt)); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileNameWin32: len=%u\n %.*ls\n", StrBuf.UniStr.Length, StrBuf.UniStr.Length, StrBuf.UniStr.Buffer); } else RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileNameWin32: Not supported (STATUS_INVALID_INFO_CLASS).\n"); /* Process image mapping - Not available on Windows 2003. */ uPtr = ~(DWORD_PTR)0; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessImageFileMapping, &uPtr, sizeof(uPtr), &cbActual); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileMapping: %p\n", uPtr); else if (rcNt == STATUS_OBJECT_TYPE_MISMATCH) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileMapping: rcNt=%#x (STATUS_OBJECT_TYPE_MISMATCH)\n", rcNt); else if (rcNt == STATUS_INVALID_INFO_CLASS) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileMapping: Not supported (STATUS_INVALID_INFO_CLASS).\n"); else RTTestIFailed("ProcessImageFileMapping: rcNt=%#x\n", rcNt); /* Handles. Broken for 64-bit input. */ uint32_t u32 = UINT32_MAX; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessHandleCount, &u32, sizeof(u32), &cbActual); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessHandleCount: %#x (%d)\n", u32, u32); else RTTestIFailed("ProcessHandleCount: rcNt=%#x\n", rcNt); /* Execute flags. */ #if 0 /* fails... wrong process handle? */ u32 = ~(DWORD_PTR)0; cbActual = 0; rcNt = NtQueryInformationProcess(g_hProcess, ProcessExecuteFlags, &u32, sizeof(u32), &cbActual); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessExecuteFlags: %#p\n", u32); else RTTestIFailed("ProcessExecuteFlags: rcNt=%#x\n", rcNt); #endif /** @todo ProcessImageInformation */ }
static void tstRTCreateProcEx6(const char *pszAsUser, const char *pszPassword) { RTTestISub("Profile environment"); const char *apszArgs[5] = { g_szExecName, "--testcase-child-6", "inherit", pszAsUser, NULL }; RTTESTI_CHECK_RC_RETV(RTEnvSetEx(RTENV_DEFAULT, "testcase-child-6", "true"), VINF_SUCCESS); /* Use the process environment first. */ RTPROCESS hProc; RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, 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); /* Use the process environment first with a little change. */ apszArgs[2] = "change-record"; RTENV hEnvChange; RTTESTI_CHECK_RC_RETV(RTEnvCreateChangeRecord(&hEnvChange), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTEnvSetEx(hEnvChange, "testcase-child-6", "changed"), VINF_SUCCESS); int rc; RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_ENV_CHANGE_RECORD, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); if (RT_SUCCESS(rc)) { ProcStatus.enmReason = RTPROCEXITREASON_ABEND; ProcStatus.iStatus = -1; 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); } /* Use profile environment this time. */ apszArgs[2] = "noinherit"; RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, RTPROC_FLAGS_PROFILE, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); if (RT_SUCCESS(rc)) { ProcStatus.enmReason = RTPROCEXITREASON_ABEND; ProcStatus.iStatus = -1; 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); } /* Use profile environment this time. */ apszArgs[2] = "noinherit-change-record"; RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_ENV_CHANGE_RECORD, NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); if (RT_SUCCESS(rc)) { ProcStatus.enmReason = RTPROCEXITREASON_ABEND; ProcStatus.iStatus = -1; 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); } RTTESTI_CHECK_RC(RTEnvDestroy(hEnvChange), VINF_SUCCESS); /* * Restore the environment and check that the PROFILE flag didn't mess with * the process environment. (Note! The bug may be elsewhere as well.) */ RTTESTI_CHECK_RC(RTEnvUnsetEx(RTENV_DEFAULT, "testcase-child-6"), VINF_SUCCESS); RTENV hEnvCur; RTTESTI_CHECK_RC_RETV(RTEnvClone(&hEnvCur, RTENV_DEFAULT), VINF_SUCCESS); uint32_t cCurrent = RTEnvCountEx(hEnvCur); uint32_t cInitial = RTEnvCountEx(g_hEnvInitial); RTTESTI_CHECK_MSG(cCurrent == cInitial, ("cCurrent=%u cInitial=%u\n", cCurrent, cInitial)); uint32_t cVars1; RTENV hEnv1, hEnv2; const char *pszEnv1, *pszEnv2; if (cCurrent >= cInitial) { hEnv1 = hEnvCur; pszEnv1 = "current"; cVars1 = cCurrent; hEnv2 = g_hEnvInitial; pszEnv2 = "initial"; } else { hEnv2 = hEnvCur; pszEnv2 = "current"; hEnv1 = g_hEnvInitial; pszEnv1 = "initial"; cVars1 = cInitial; } for (uint32_t i = 0; i < cVars1; i++) { char szValue1[_16K]; char szVarNm[_1K]; rc = RTEnvGetByIndexEx(hEnv1, i, szVarNm, sizeof(szVarNm), szValue1, sizeof(szValue1)); if (RT_SUCCESS(rc)) { char szValue2[_16K]; rc = RTEnvGetEx(hEnv2, szVarNm, szValue2, sizeof(szValue2), NULL); if (RT_SUCCESS(rc)) { if (strcmp(szValue1, szValue2) != 0) { RTTestIFailed("Variable '%s' differs", szVarNm); RTTestIFailureDetails("%s: '%s'\n" "%s: '%s'\n", pszEnv1, szValue1, pszEnv2, szValue2); } } else RTTestIFailed("RTEnvGetEx(%s,%s,,) failed: %Rrc", pszEnv2, szVarNm, rc); } else RTTestIFailed("RTEnvGetByIndexEx(%s,%u,,,,) failed: %Rrc", pszEnv1, i, rc); } }
int main(int argc, char *argv[]) { /* * Init runtime. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTHeapOffset", &hTest); if (rc) return rc; RTTestBanner(hTest); /* * Create a heap. */ RTTestSub(hTest, "Basics"); static uint8_t s_abMem[128*1024]; RTHEAPOFFSET Heap; RTTESTI_CHECK_RC(rc = RTHeapOffsetInit(&Heap, &s_abMem[1], sizeof(s_abMem) - 1), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); /* * Try allocate. */ static struct TstHeapOffsetOps { size_t cb; unsigned uAlignment; void *pvAlloc; unsigned iFreeOrder; } s_aOps[] = { { 16, 0, NULL, 0 }, // 0 { 16, 4, NULL, 1 }, { 16, 8, NULL, 2 }, { 16, 16, NULL, 5 }, { 16, 32, NULL, 4 }, { 32, 0, NULL, 3 }, // 5 { 31, 0, NULL, 6 }, { 1024, 0, NULL, 8 }, { 1024, 32, NULL, 10 }, { 1024, 32, NULL, 12 }, { PAGE_SIZE, PAGE_SIZE, NULL, 13 }, // 10 { 1024, 32, NULL, 9 }, { PAGE_SIZE, 32, NULL, 11 }, { PAGE_SIZE, PAGE_SIZE, NULL, 14 }, { 16, 0, NULL, 15 }, { 9, 0, NULL, 7 }, // 15 { 16, 0, NULL, 7 }, { 36, 0, NULL, 7 }, { 16, 0, NULL, 7 }, { 12344, 0, NULL, 7 }, { 50, 0, NULL, 7 }, // 20 { 16, 0, NULL, 7 }, }; uint32_t i; RTHeapOffsetDump(Heap, (PFNRTHEAPOFFSETPRINTF)RTPrintf); /** @todo Add some detail info output with a signature identical to RTPrintf. */ size_t cbBefore = RTHeapOffsetGetFreeSize(Heap); static char const s_szFill[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; /* allocate */ for (i = 0; i < RT_ELEMENTS(s_aOps); i++) { s_aOps[i].pvAlloc = RTHeapOffsetAlloc(Heap, s_aOps[i].cb, s_aOps[i].uAlignment); RTTESTI_CHECK_MSG(s_aOps[i].pvAlloc, ("RTHeapOffsetAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i)); if (!s_aOps[i].pvAlloc) return RTTestSummaryAndDestroy(hTest); memset(s_aOps[i].pvAlloc, s_szFill[i], s_aOps[i].cb); RTTESTI_CHECK_MSG(RT_ALIGN_P(s_aOps[i].pvAlloc, (s_aOps[i].uAlignment ? s_aOps[i].uAlignment : 8)) == s_aOps[i].pvAlloc, ("RTHeapOffsetAlloc(%p, %#x, %#x,) -> %p\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i)); if (!s_aOps[i].pvAlloc) return RTTestSummaryAndDestroy(hTest); } /* free and allocate the same node again. */ for (i = 0; i < RT_ELEMENTS(s_aOps); i++) { if (!s_aOps[i].pvAlloc) continue; //RTPrintf("debug: i=%d pv=%#x cb=%#zx align=%#zx cbReal=%#zx\n", i, s_aOps[i].pvAlloc, // s_aOps[i].cb, s_aOps[i].uAlignment, RTHeapOffsetSize(Heap, s_aOps[i].pvAlloc)); size_t cbBeforeSub = RTHeapOffsetGetFreeSize(Heap); RTHeapOffsetFree(Heap, s_aOps[i].pvAlloc); size_t cbAfterSubFree = RTHeapOffsetGetFreeSize(Heap); void *pv; pv = RTHeapOffsetAlloc(Heap, s_aOps[i].cb, s_aOps[i].uAlignment); RTTESTI_CHECK_MSG(pv, ("RTHeapOffsetAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i)); if (!pv) return RTTestSummaryAndDestroy(hTest); //RTPrintf("debug: i=%d pv=%p cbReal=%#zx cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx \n", i, pv, RTHeapOffsetSize(Heap, pv), // cbBeforeSub, cbAfterSubFree, RTHeapOffsetGetFreeSize(Heap)); if (pv != s_aOps[i].pvAlloc) RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: Free+Alloc returned different address. new=%p old=%p i=%d\n", pv, s_aOps[i].pvAlloc, i); s_aOps[i].pvAlloc = pv; size_t cbAfterSubAlloc = RTHeapOffsetGetFreeSize(Heap); if (cbBeforeSub != cbAfterSubAlloc) { RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx. i=%d\n", cbBeforeSub, cbAfterSubFree, cbAfterSubAlloc, i); //return 1; - won't work correctly until we start creating free block instead of donating memory on alignment. } } /* make a copy of the heap and the to-be-freed list. */ static uint8_t s_abMemCopy[sizeof(s_abMem)]; memcpy(s_abMemCopy, s_abMem, sizeof(s_abMem)); uintptr_t offDelta = (uintptr_t)&s_abMemCopy[0] - (uintptr_t)&s_abMem[0]; RTHEAPOFFSET hHeapCopy = (RTHEAPOFFSET)((uintptr_t)Heap + offDelta); static struct TstHeapOffsetOps s_aOpsCopy[RT_ELEMENTS(s_aOps)]; memcpy(&s_aOpsCopy[0], &s_aOps[0], sizeof(s_aOps)); /* free it in a specific order. */ int cFreed = 0; for (i = 0; i < RT_ELEMENTS(s_aOps); i++) { unsigned j; for (j = 0; j < RT_ELEMENTS(s_aOps); j++) { if ( s_aOps[j].iFreeOrder != i || !s_aOps[j].pvAlloc) continue; //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapOffsetGetFreeSize(Heap), s_aOps[j].cb, s_aOps[j].pvAlloc); RTHeapOffsetFree(Heap, s_aOps[j].pvAlloc); s_aOps[j].pvAlloc = NULL; cFreed++; } } RTTESTI_CHECK(cFreed == RT_ELEMENTS(s_aOps)); RTTestIPrintf(RTTESTLVL_ALWAYS, "i=done free=%d\n", RTHeapOffsetGetFreeSize(Heap)); /* check that we're back at the right amount of free memory. */ size_t cbAfter = RTHeapOffsetGetFreeSize(Heap); if (cbBefore != cbAfter) { RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: Either we've split out an alignment chunk at the start, or we've got\n" " an alloc/free accounting bug: cbBefore=%d cbAfter=%d\n", cbBefore, cbAfter); RTHeapOffsetDump(Heap, (PFNRTHEAPOFFSETPRINTF)RTPrintf); } /* relocate and free the bits in heap2 now. */ RTTestSub(hTest, "Relocated Heap"); /* free it in a specific order. */ int cFreed2 = 0; for (i = 0; i < RT_ELEMENTS(s_aOpsCopy); i++) { unsigned j; for (j = 0; j < RT_ELEMENTS(s_aOpsCopy); j++) { if ( s_aOpsCopy[j].iFreeOrder != i || !s_aOpsCopy[j].pvAlloc) continue; //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapOffsetGetFreeSize(hHeapCopy), s_aOpsCopy[j].cb, s_aOpsCopy[j].pvAlloc); RTHeapOffsetFree(hHeapCopy, (uint8_t *)s_aOpsCopy[j].pvAlloc + offDelta); s_aOpsCopy[j].pvAlloc = NULL; cFreed2++; } } RTTESTI_CHECK(cFreed2 == RT_ELEMENTS(s_aOpsCopy)); /* check that we're back at the right amount of free memory. */ size_t cbAfterCopy = RTHeapOffsetGetFreeSize(hHeapCopy); RTTESTI_CHECK_MSG(cbAfterCopy == cbAfter, ("cbAfterCopy=%zu cbAfter=%zu\n", cbAfterCopy, cbAfter)); /* * Use random allocation pattern */ RTTestSub(hTest, "Random Test"); RTTESTI_CHECK_RC(rc = RTHeapOffsetInit(&Heap, &s_abMem[1], sizeof(s_abMem) - 1), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTRAND hRand; RTTESTI_CHECK_RC(rc = RTRandAdvCreateParkMiller(&hRand), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); #if 0 RTRandAdvSeed(hRand, 42); #else RTRandAdvSeed(hRand, RTTimeNanoTS()); #endif static struct { size_t cb; void *pv; } s_aHistory[1536]; RT_ZERO(s_aHistory); for (unsigned iTest = 0; iTest < 131072; iTest++) { i = RTRandAdvU32Ex(hRand, 0, RT_ELEMENTS(s_aHistory) - 1); if (!s_aHistory[i].pv) { uint32_t uAlignment = 1 << RTRandAdvU32Ex(hRand, 0, 7); s_aHistory[i].cb = RTRandAdvU32Ex(hRand, 9, 1024); s_aHistory[i].pv = RTHeapOffsetAlloc(Heap, s_aHistory[i].cb, uAlignment); if (!s_aHistory[i].pv) { s_aHistory[i].cb = 9; s_aHistory[i].pv = RTHeapOffsetAlloc(Heap, s_aHistory[i].cb, 0); } if (s_aHistory[i].pv) memset(s_aHistory[i].pv, 0xbb, s_aHistory[i].cb); } else { RTHeapOffsetFree(Heap, s_aHistory[i].pv); s_aHistory[i].pv = NULL; } if ((iTest % 7777) == 7776) { /* exhaust the heap */ for (i = 0; i < RT_ELEMENTS(s_aHistory) && RTHeapOffsetGetFreeSize(Heap) >= 256; i++) if (!s_aHistory[i].pv) { s_aHistory[i].cb = RTRandAdvU32Ex(hRand, 256, 16384); s_aHistory[i].pv = RTHeapOffsetAlloc(Heap, s_aHistory[i].cb, 0); } for (i = 0; i < RT_ELEMENTS(s_aHistory) && RTHeapOffsetGetFreeSize(Heap); i++) { if (!s_aHistory[i].pv) { s_aHistory[i].cb = 1; s_aHistory[i].pv = RTHeapOffsetAlloc(Heap, s_aHistory[i].cb, 1); } if (s_aHistory[i].pv) memset(s_aHistory[i].pv, 0x55, s_aHistory[i].cb); } RTTESTI_CHECK_MSG(RTHeapOffsetGetFreeSize(Heap) == 0, ("%zu\n", RTHeapOffsetGetFreeSize(Heap))); } else if ((iTest % 7777) == 1111) { /* free all */ for (i = 0; i < RT_ELEMENTS(s_aHistory); i++) { RTHeapOffsetFree(Heap, s_aHistory[i].pv); s_aHistory[i].pv = NULL; } size_t cbAfterRand = RTHeapOffsetGetFreeSize(Heap); RTTESTI_CHECK_MSG(cbAfterRand == cbAfter, ("cbAfterRand=%zu cbAfter=%zu\n", cbAfterRand, cbAfter)); } } /* free the rest. */ for (i = 0; i < RT_ELEMENTS(s_aHistory); i++) { RTHeapOffsetFree(Heap, s_aHistory[i].pv); s_aHistory[i].pv = NULL; } /* check that we're back at the right amount of free memory. */ size_t cbAfterRand = RTHeapOffsetGetFreeSize(Heap); RTTESTI_CHECK_MSG(cbAfterRand == cbAfter, ("cbAfterRand=%zu cbAfter=%zu\n", cbAfterRand, cbAfter)); return RTTestSummaryAndDestroy(hTest); }
static void test2(RTTEST hTest) { RTTestSub(hTest, "UTF-8 upper/lower encoding assumption"); #define CHECK_EQUAL(str1, str2) \ do \ { \ RTTESTI_CHECK(strlen((str1).c_str()) == (str1).length()); \ RTTESTI_CHECK((str1).length() == (str2).length()); \ RTTESTI_CHECK(mymemcmp((str1).c_str(), (str2).c_str(), (str2).length() + 1) == 0); \ } while (0) RTCString strTmp, strExpect; char szDst[16]; /* Some simple ascii stuff. */ strTmp = "abcdefghijklmnopqrstuvwxyz0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ;-+/\\"; strExpect = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ;-+/\\"; strTmp.toUpper(); CHECK_EQUAL(strTmp, strExpect); strTmp.toLower(); strExpect = "abcdefghijklmnopqrstuvwxyz0123456abcdefghijklmnopqrstuvwxyz;-+/\\"; CHECK_EQUAL(strTmp, strExpect); strTmp = "abcdefghijklmnopqrstuvwxyz0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ;-+/\\"; strTmp.toLower(); CHECK_EQUAL(strTmp, strExpect); /* Collect all upper and lower case code points. */ RTCString strLower(""); strLower.reserve(_4M); RTCString strUpper(""); strUpper.reserve(_4M); for (RTUNICP uc = 1; uc <= 0x10fffd; uc++) { /* Unicode 4.01, I think, introduced a few codepoints with lower/upper mappings that aren't up for roundtrips and which case folding has a different UTF-8 length. We'll just skip them here as there are very few: - Dotless small i and dotless capital I folds into ASCII I and i. - The small letter long s folds to ASCII S. - Greek prosgegrammeni folds to iota, which is a letter with both upper and lower case foldings of its own. */ if (uc == 0x131 || uc == 0x130 || uc == 0x17f || 0x1fbe) continue; if (RTUniCpIsLower(uc)) { RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc)); strLower.appendCodePoint(uc); } if (RTUniCpIsUpper(uc)) { RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc)); strUpper.appendCodePoint(uc); } } RTTESTI_CHECK(strlen(strLower.c_str()) == strLower.length()); RTTESTI_CHECK(strlen(strUpper.c_str()) == strUpper.length()); /* Fold each code point in the lower case string and check that it encodes into the same or less number of bytes. */ size_t cch = 0; const char *pszCur = strLower.c_str(); RTCString strUpper2(""); strUpper2.reserve(strLower.length() + 64); for (;;) { RTUNICP ucLower; const char * const pszPrev = pszCur; RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucLower), VINF_SUCCESS); size_t const cchSrc = pszCur - pszPrev; if (!ucLower) break; RTUNICP const ucUpper = RTUniCpToUpper(ucLower); const char *pszDstEnd = RTStrPutCp(szDst, ucUpper); size_t const cchDst = pszDstEnd - &szDst[0]; RTTESTI_CHECK_MSG(cchSrc >= cchDst, ("ucLower=%#x %u bytes; ucUpper=%#x %u bytes\n", ucLower, cchSrc, ucUpper, cchDst)); cch += cchDst; strUpper2.appendCodePoint(ucUpper); /* roundtrip stability */ RTUNICP const ucUpper2 = RTUniCpToUpper(ucUpper); RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper)); RTUNICP const ucLower2 = RTUniCpToLower(ucUpper); RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower)); RTUNICP const ucUpper3 = RTUniCpToUpper(ucLower2); RTTESTI_CHECK_MSG(ucUpper3 == ucUpper, ("ucUpper3=%#x ucUpper=%#x\n", ucUpper3, ucUpper)); pszDstEnd = RTStrPutCp(szDst, ucLower2); size_t const cchLower2 = pszDstEnd - &szDst[0]; RTTESTI_CHECK_MSG(cchDst == cchLower2, ("ucLower2=%#x %u bytes; ucUpper=%#x %u bytes; ucLower=%#x\n", ucLower2, cchLower2, ucUpper, cchDst, ucLower)); } RTTESTI_CHECK(strlen(strUpper2.c_str()) == strUpper2.length()); RTTESTI_CHECK_MSG(cch == strUpper2.length(), ("cch=%u length()=%u\n", cch, strUpper2.length())); /* the toUpper method shall do the same thing. */ strTmp = strLower; CHECK_EQUAL(strTmp, strLower); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); /* Ditto for the upper case string. */ cch = 0; pszCur = strUpper.c_str(); RTCString strLower2(""); strLower2.reserve(strUpper.length() + 64); for (;;) { RTUNICP ucUpper; const char * const pszPrev = pszCur; RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucUpper), VINF_SUCCESS); size_t const cchSrc = pszCur - pszPrev; if (!ucUpper) break; RTUNICP const ucLower = RTUniCpToLower(ucUpper); const char *pszDstEnd = RTStrPutCp(szDst, ucLower); size_t const cchDst = pszDstEnd - &szDst[0]; RTTESTI_CHECK_MSG(cchSrc >= cchDst, ("ucUpper=%#x %u bytes; ucLower=%#x %u bytes\n", ucUpper, cchSrc, ucLower, cchDst)); cch += cchDst; strLower2.appendCodePoint(ucLower); /* roundtrip stability */ RTUNICP const ucLower2 = RTUniCpToLower(ucLower); RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower)); RTUNICP const ucUpper2 = RTUniCpToUpper(ucLower); RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper)); RTUNICP const ucLower3 = RTUniCpToLower(ucUpper2); RTTESTI_CHECK_MSG(ucLower3 == ucLower, ("ucLower3=%#x ucLower=%#x\n", ucLower3, ucLower)); pszDstEnd = RTStrPutCp(szDst, ucUpper2); size_t const cchUpper2 = pszDstEnd - &szDst[0]; RTTESTI_CHECK_MSG(cchDst == cchUpper2, ("ucUpper2=%#x %u bytes; ucLower=%#x %u bytes\n", ucUpper2, cchUpper2, ucLower, cchDst)); } RTTESTI_CHECK(strlen(strLower2.c_str()) == strLower2.length()); RTTESTI_CHECK_MSG(cch == strLower2.length(), ("cch=%u length()=%u\n", cch, strLower2.length())); strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); /* Checks of folding stability when nothing shall change. */ strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper); strTmp = strUpper2; CHECK_EQUAL(strTmp, strUpper2); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); strTmp = strLower; CHECK_EQUAL(strTmp, strLower); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower); strTmp = strLower2; CHECK_EQUAL(strTmp, strLower2); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); /* Check folding stability for roundtrips. */ strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); strTmp.toUpper(); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); strTmp.toUpper(); strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); strTmp = strLower; CHECK_EQUAL(strTmp, strLower); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); strTmp.toLower(); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); strTmp.toLower(); strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); }
int main() { RTTIMESPEC Now; RTTIMESPEC Ts1; RTTIMESPEC Ts2; RTTIME T1; RTTIME T2; #ifdef RTTIME_INCL_TIMEVAL struct timeval Tv1; struct timeval Tv2; struct timespec Tsp1; struct timespec Tsp2; #endif RTTEST hTest; int rc = RTTestInitAndCreate("tstRTTimeSpec", &hTest); if (rc) return rc; /* * Simple test with current time. */ RTTestSub(hTest, "Current time (UTC)"); CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Simple test with current local time. */ RTTestSub(hTest, "Current time (local)"); CHECK_NZ(RTTimeLocalNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Some simple tests with fixed dates (just checking for smoke). */ RTTestSub(hTest, "Smoke"); TEST_NS(INT64_C(0)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(86400000000000)); CHECK_TIME(&T1, 1970,01,02, 00,00,00, 0, 2, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(-1)); CHECK_TIME(&T1, 1969,12,31, 23,59,59,999999999, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Test the limits. */ RTTestSub(hTest, "Extremes"); TEST_NS(INT64_MAX); TEST_NS(INT64_MIN); TEST_SEC(1095379198); CHECK_TIME(&T1, 2004, 9,16, 23,59,58, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379199); CHECK_TIME(&T1, 2004, 9,16, 23,59,59, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379200); CHECK_TIME(&T1, 2004, 9,17, 00,00,00, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379201); CHECK_TIME(&T1, 2004, 9,17, 00,00,01, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); /* * Test normalization (UTC). */ RTTestSub(hTest, "Normalization (UTC)"); /* simple */ CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); T2 = T1; CHECK_NZ(RTTimeNormalize(&T1)); if (memcmp(&T1, &T2, sizeof(T1))) RTTestIFailed("simple normalization failed\n"); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); CHECK_NZ(RTTimeSpecIsEqual(&Ts1, &Now)); /* a few partial dates. */ memset(&T1, 0, sizeof(T1)); SET_TIME( &T1, 1970,01,01, 00,00,00, 0, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1970,00,00, 00,00,00, 1, 1, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,12,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1968,01,30, 00,19,24, 5, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1968,01,30, 00,19,24, 5, 30, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 1969,01,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,01,31, 00, 9, 2, 7, 31, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,03,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,03,31, 00, 9, 2, 7, 90, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,31, 00,00,00, 9, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,31, 00,00,00, 9, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,30, 00,00,00, 30, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,30, 00,00,00, 30, 364, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 363, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,29, 00,00,00, 30, 363, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 362, 6, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,28, 00,00,00, 30, 362, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,27, 00,00,00, 30, 0, 5, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,27, 00,00,00, 30, 361, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 360, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,26, 00,00,00, 30, 360, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,25, 00,00,00, 12, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,25, 00,00,00, 12, 359, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,24, 00,00,00, 16, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,24, 00,00,00, 16, 358, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* outside the year table range */ SET_TIME( &T1, 1200,01,30, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1200,01,30, 00,00,00, 2, 30, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2555,11,29, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 2, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2555,00,00, 00,00,00, 3, 333, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 3, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* time overflow */ SET_TIME( &T1, 1969,12,30, 255,255,255, UINT32_MAX, 364, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01, 9, 19,19,19,294967295, 9, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* date overflow */ SET_TIME( &T1, 2007,11,36, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,67, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,98, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2006,24,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2003,60,37, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2003,00,00, 02,15,23, 1,1801, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Conversions. */ #define CHECK_NSEC(Ts1, T2) \ do { \ RTTIMESPEC TsTmp; \ RTTESTI_CHECK_MSG( RTTimeSpecGetNano(&(Ts1)) == RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2))), \ ("line %d: %RI64, %RI64\n", __LINE__, \ RTTimeSpecGetNano(&(Ts1)), RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2)))) ); \ } while (0) RTTestSub(hTest, "Conversions, positive"); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetDosSeconds(&Ts2, 0) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetDosSeconds(&Ts2) == 0); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetNtTime(&Ts2, INT64_C(119600064000000000)) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNtTime(&Ts2) == INT64_C(119600064000000000)); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetSeconds(&Ts2, 1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetSeconds(&Ts2) == 1); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMilli(&Ts2, 1000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMilli(&Ts2) == 1000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMicro(&Ts2, 1000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetNano(&Ts2, 1000000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000000); CHECK_NSEC(Ts2, T1); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1970,01,01, 00,00,01, 5000, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = 1; Tv1.tv_usec = 5; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1970,01,01, 00,00,01, 5, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = 1; Tsp1.tv_nsec = 5; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif RTTestSub(hTest, "Conversions, negative"); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1969,12,31, 23,59,58,999995000, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = -2; Tv1.tv_usec = 999995; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetMicro(&Ts2) == -1000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1969,12,31, 23,59,58,999999995, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = -2; Tsp1.tv_nsec = 999999995; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetNano(&Ts2) == -1000000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
/* Test 16-bit sample conversion (16-bit -> internal -> 16-bit). */ static int tstConversion16(RTTEST hTest) { unsigned i; uint32_t cBufSize = 256; PDMPCMPROPS props; RTTestSubF(hTest, "Sample conversion 16-bit"); PDMAUDIOSTREAMCFG cfg_p = { 44100, /* Hz */ 1 /* Channels */, AUD_FMT_S16 /* Format */, PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ }; int rc = DrvAudioStreamCfgToProps(&cfg_p, &props); AssertRC(rc); PDMAUDIOMIXBUF parent; RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize)); PDMAUDIOSTREAMCFG cfg_c = /* Upmixing to parent */ { 22050, /* Hz */ 1 /* Channels */, AUD_FMT_S16 /* Format */, PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ }; rc = DrvAudioStreamCfgToProps(&cfg_c, &props); AssertRC(rc); PDMAUDIOMIXBUF child; RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize)); RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent)); /* 16-bit signed. More or less exclusively used as output, and usually as input, too. */ int16_t samples[16] = { 0xAA, 0xBB, INT16_MIN, INT16_MIN + 1, INT16_MIN / 2, -3, -2, -1, 0, 1, 2, 3, INT16_MAX / 2, INT16_MAX - 1, INT16_MAX, 0 }; /* * Writing + mixing from child -> parent, sequential. */ uint32_t cbBuf = 256; char achBuf[256]; uint32_t read, written, mixed, temp; uint32_t cChildFree = cBufSize; uint32_t cChildMixed = 0; uint32_t cSamplesChild = 16; uint32_t cSamplesParent = cSamplesChild * 2 - 2; uint32_t cSamplesRead = 0; /**** 16-bit signed samples ****/ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 16-bit\n", cfg_c.uHz, cfg_c.cChannels); RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written)); RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written)); RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed)); temp = AudioMixBufProcessed(&parent); RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp)); RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child)); for (;;) { RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read)); if (!read) break; cSamplesRead += read; AudioMixBufFinish(&parent, read); } RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead)); /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */ /* NB: This also checks that the default volume setting is 0dB attenuation. */ int16_t *pSrc16 = &samples[0]; int16_t *pDst16 = (int16_t *)achBuf; for (i = 0; i < cSamplesChild - 1; ++i) { RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16)); pSrc16 += 1; pDst16 += 2; } RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0); RTTESTI_CHECK(AudioMixBufMixed(&child) == 0); AudioMixBufDestroy(&parent); AudioMixBufDestroy(&child); return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS; }
/* Test volume control. */ static int tstVolume(RTTEST hTest) { unsigned i; uint32_t cBufSize = 256; PDMPCMPROPS props; RTTestSubF(hTest, "Volume control"); /* Same for parent/child. */ PDMAUDIOSTREAMCFG cfg = { 44100, /* Hz */ 2 /* Channels */, AUD_FMT_S16 /* Format */, PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ }; int rc = DrvAudioStreamCfgToProps(&cfg, &props); AssertRC(rc); PDMAUDIOVOLUME vol = { false, 0, 0 }; /* Not muted. */ PDMAUDIOMIXBUF parent; RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize)); PDMAUDIOMIXBUF child; RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize)); RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent)); /* A few 16-bit signed samples. */ int16_t samples[16] = { INT16_MIN, INT16_MIN + 1, -128, -64, -4, -1, 0, 1, 2, 255, 256, INT16_MAX / 2, INT16_MAX - 2, INT16_MAX - 1, INT16_MAX, 0 }; /* * Writing + mixing from child -> parent. */ uint32_t cbBuf = 256; char achBuf[256]; uint32_t read, written, mixed; uint32_t cChildFree = cBufSize; uint32_t cChildMixed = 0; uint32_t cSamplesChild = 8; uint32_t cSamplesParent = cSamplesChild; uint32_t cSamplesRead; int16_t *pSrc16; int16_t *pDst16; /**** Volume control test ****/ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Volume control test %uHz %uch \n", cfg.uHz, cfg.cChannels); /* 1) Full volume/0dB attenuation (255). */ vol.uLeft = vol.uRight = 255; AudioMixBufSetVolume(&child, &vol); RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written)); RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written)); RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed)); cSamplesRead = 0; for (;;) { RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read)); if (!read) break; cSamplesRead += read; AudioMixBufFinish(&parent, read); } RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead)); /* Check that at 0dB the samples came out unharmed. */ pSrc16 = &samples[0]; pDst16 = (int16_t *)achBuf; for (i = 0; i < cSamplesParent * 2 /* stereo */; ++i) { RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16)); ++pSrc16; ++pDst16; } AudioMixBufReset(&child); /* 2) Half volume/-6dB attenuation (16 steps down). */ vol.uLeft = vol.uRight = 255 - 16; AudioMixBufSetVolume(&child, &vol); RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written)); RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written)); RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed)); cSamplesRead = 0; for (;;) { RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read)); if (!read) break; cSamplesRead += read; AudioMixBufFinish(&parent, read); } RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead)); /* Check that at -6dB the sample values are halved. */ pSrc16 = &samples[0]; pDst16 = (int16_t *)achBuf; for (i = 0; i < cSamplesParent * 2 /* stereo */; ++i) { /* Watch out! For negative values, x >> 1 is not the same as x / 2. */ RTTESTI_CHECK_MSG(*pSrc16 >> 1 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16)); ++pSrc16; ++pDst16; } AudioMixBufDestroy(&parent); AudioMixBufDestroy(&child); return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS; }
/* Test 8-bit sample conversion (8-bit -> internal -> 8-bit). */ static int tstConversion8(RTTEST hTest) { unsigned i; uint32_t cBufSize = 256; PDMPCMPROPS props; RTTestSubF(hTest, "Sample conversion"); PDMAUDIOSTREAMCFG cfg_p = { 44100, /* Hz */ 1 /* Channels */, AUD_FMT_U8 /* Format */, PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ }; int rc = DrvAudioStreamCfgToProps(&cfg_p, &props); AssertRC(rc); PDMAUDIOMIXBUF parent; RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize)); /* Child uses half the sample rate; that ensures the mixing engine can't * take shortcuts and performs conversion. Because conversion to double * the sample rate effectively inserts one additional sample between every * two source samples, N source samples will be converted to N * 2 - 1 * samples. However, the last source sample will be saved for later * interpolation and not immediately output. */ PDMAUDIOSTREAMCFG cfg_c = /* Upmixing to parent */ { 22050, /* Hz */ 1 /* Channels */, AUD_FMT_U8 /* Format */, PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ }; rc = DrvAudioStreamCfgToProps(&cfg_c, &props); AssertRC(rc); PDMAUDIOMIXBUF child; RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize)); RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent)); /* 8-bit unsigned samples. Often used with SB16 device. */ uint8_t samples[16] = { 0xAA, 0xBB, 0, 1, 43, 125, 126, 127, 128, 129, 130, 131, 132, UINT8_MAX - 1, UINT8_MAX, 0 }; /* * Writing + mixing from child -> parent, sequential. */ uint32_t cbBuf = 256; char achBuf[256]; uint32_t read, written, mixed, temp; uint32_t cChildFree = cBufSize; uint32_t cChildMixed = 0; uint32_t cSamplesChild = 16; uint32_t cSamplesParent = cSamplesChild * 2 - 2; uint32_t cSamplesRead = 0; /**** 8-bit unsigned samples ****/ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 8-bit\n", cfg_c.uHz, cfg_c.cChannels); RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written)); RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written)); RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed)); temp = AudioMixBufProcessed(&parent); RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp)); RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child)); for (;;) { RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read)); if (!read) break; cSamplesRead += read; AudioMixBufFinish(&parent, read); } RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead)); /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */ /* NB: This also checks that the default volume setting is 0dB attenuation. */ uint8_t *pSrc8 = &samples[0]; uint8_t *pDst8 = (uint8_t *)achBuf; for (i = 0; i < cSamplesChild - 1; ++i) { RTTESTI_CHECK_MSG(*pSrc8 == *pDst8, ("index %u: Dst=%d, Src=%d\n", i, *pDst8, *pSrc8)); pSrc8 += 1; pDst8 += 2; } RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0); RTTESTI_CHECK(AudioMixBufMixed(&child) == 0); AudioMixBufDestroy(&parent); AudioMixBufDestroy(&child); return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : 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 testParserAndSplitter(RTTEST hTest) { static struct { uint16_t cComps; uint16_t cchPath; uint16_t offSuffix; const char *pszPath; uint16_t fProps; uint32_t fFlags; } const s_aTests[] = { { 2, 5, 5, "/bin/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_DIR_SLASH, RTPATH_STR_F_STYLE_UNIX }, { 2, 13, 9, "C:/Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_DOS }, { 2, 13, 10, "C://Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_DOS }, { 2, 12, 8, "C:Config.sys", RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_DOS }, { 1, 10, 6, "Config.sys", RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_DOS }, { 1, 4, 4, "//./", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE, RTPATH_STR_F_STYLE_DOS }, { 2, 5, 5, "//./f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_DOS }, { 2, 5, 6, "//.//f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_DOS }, { 3, 7, 7, "//././f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS, RTPATH_STR_F_STYLE_DOS }, { 3, 8, 8, "//.././f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS, RTPATH_STR_F_STYLE_DOS }, { 3, 9, 9, "//../../f", RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOTDOT_REFS, RTPATH_STR_F_STYLE_DOS }, { 1, 1, 1, "/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE, RTPATH_STR_F_STYLE_UNIX }, { 2, 4, 4, "/bin", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 2, 5, 5, "/bin/", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_DIR_SLASH, RTPATH_STR_F_STYLE_UNIX }, { 3, 7, 7, "/bin/ls", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 3, 12, 7, "/etc/rc.conf", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX, RTPATH_STR_F_STYLE_UNIX }, { 1, 1, 2, "//", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_UNIX }, { 1, 1, 3, "///", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_UNIX }, { 3, 6, 7, "/.//bin", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_DOT_REFS | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 1, 3, 3, "bin", RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 1, 4, 4, "bin/", RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH, RTPATH_STR_F_STYLE_UNIX }, { 1, 4, 7, "bin////", RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH | RTPATH_PROP_EXTRA_SLASHES, RTPATH_STR_F_STYLE_UNIX }, { 3, 10, 10, "bin/../usr", RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 11, 11, "/bin/../usr", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.../u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.b./u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/..c/u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/d../u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.e/.u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.f/.u", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 4, 8, 8, "/a/.g/u.", RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME, RTPATH_STR_F_STYLE_UNIX }, { 3, 9, 10, "/a/h/u.ext", RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_MIDDLE }, { 3, 9, 9, "a/h/u.ext", RTPATH_PROP_RELATIVE, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_MIDDLE }, { 3, 9, 10, "a/h/u.ext/", RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_MIDDLE }, }; char szPath1[RTPATH_MAX]; union { RTPATHPARSED Parsed; RTPATHSPLIT Split; uint8_t ab[4096]; } u; RTTestSub(hTest, "RTPathParse"); for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++) { memset(&u, i & 1 ? 0xff : 0, sizeof(u)); int rc = RTPathParse(s_aTests[i].pszPath, &u.Parsed, sizeof(u), s_aTests[i].fFlags); if ( rc != VINF_SUCCESS || s_aTests[i].cComps != u.Parsed.cComps || s_aTests[i].fProps != u.Parsed.fProps || s_aTests[i].offSuffix != u.Parsed.offSuffix || s_aTests[i].cchPath != u.Parsed.cchPath) { RTTestFailed(hTest, "i=%d rc=%Rrc %s", i, rc, s_aTests[i].pszPath); RTTestFailureDetails(hTest, " cComps %u, got %u\n" " fProps %#x, got %#x, xor=>%#x\n" " offSuffix %u, got %u\n" " cchPath %u, got %u\n" , s_aTests[i].cComps, u.Parsed.cComps, s_aTests[i].fProps, u.Parsed.fProps, s_aTests[i].fProps ^ u.Parsed.fProps, s_aTests[i].offSuffix, u.Parsed.offSuffix, s_aTests[i].cchPath, u.Parsed.cchPath); } else { rc = RTPathParsedReassemble(s_aTests[i].pszPath, &u.Parsed, s_aTests[i].fFlags & ~RTPATH_STR_F_MIDDLE, szPath1, sizeof(szPath1)); if (rc == VINF_SUCCESS) { RTTESTI_CHECK_MSG(strlen(szPath1) == s_aTests[i].cchPath, ("%s\n", szPath1)); if ( !(u.Parsed.fProps & RTPATH_PROP_EXTRA_SLASHES) && (s_aTests[i].fFlags & RTPATH_STR_F_STYLE_MASK) != RTPATH_STR_F_STYLE_DOS) RTTESTI_CHECK_MSG(strcmp(szPath1, s_aTests[i].pszPath) == 0, ("%s\n", szPath1)); } else RTTestIFailed("RTPathParsedReassemble -> %Rrc", rc); } } RTTestSub(hTest, "RTPathSplit"); for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++) { memset(&u, i & 1 ? 0xff : 0, sizeof(u)); int rc = RTPathSplit(s_aTests[i].pszPath, &u.Split, sizeof(u), s_aTests[i].fFlags); if ( rc != VINF_SUCCESS || s_aTests[i].cComps != u.Split.cComps || s_aTests[i].fProps != u.Split.fProps || s_aTests[i].cchPath != u.Split.cchPath) { RTTestFailed(hTest, "i=%d rc=%Rrc %s", i, rc, s_aTests[i].pszPath); RTTestFailureDetails(hTest, " cComps %u, got %u\n" " fProps %#x, got %#x, xor=>%#x\n" " cchPath %u, got %u\n" , s_aTests[i].cComps, u.Split.cComps, s_aTests[i].fProps, u.Split.fProps, s_aTests[i].fProps ^ u.Split.fProps, s_aTests[i].cchPath, u.Split.cchPath); } else { RTTESTI_CHECK_MSG(*u.Split.pszSuffix == '\0' || *u.Split.pszSuffix == '.', ("%s", u.Split.pszSuffix)); for (uint32_t idxComp = RTPATH_PROP_HAS_ROOT_SPEC(u.Split.fProps); idxComp < u.Split.cComps; idxComp++) if ( (s_aTests[i].fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_DOS ? strpbrk(u.Split.apszComps[idxComp], "/\\") : strchr(u.Split.apszComps[idxComp], RTPATH_SLASH) ) RTTestFailed(hTest, "i=%d idxComp=%d '%s'", i, idxComp, u.Split.apszComps[idxComp]); PRTPATHSPLIT pSplit = NULL; RTTESTI_CHECK_RC(rc = RTPathSplitA(s_aTests[i].pszPath, &pSplit, s_aTests[i].fFlags), VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK(pSplit); RTTESTI_CHECK(pSplit->cComps == u.Split.cComps); RTTESTI_CHECK(pSplit->fProps == u.Split.fProps); RTTESTI_CHECK(pSplit->cchPath == u.Split.cchPath); RTTESTI_CHECK(pSplit->cbNeeded == u.Split.cbNeeded); RTTESTI_CHECK(!strcmp(pSplit->pszSuffix, u.Split.pszSuffix)); for (uint32_t idxComp = 0; idxComp < u.Split.cComps; idxComp++) RTTESTI_CHECK(!strcmp(pSplit->apszComps[idxComp], pSplit->apszComps[idxComp])); RTPathSplitFree(pSplit); } rc = RTPathSplitReassemble(&u.Split, s_aTests[i].fFlags & ~RTPATH_STR_F_MIDDLE, szPath1, sizeof(szPath1)); if (rc == VINF_SUCCESS) { RTTESTI_CHECK_MSG(strlen(szPath1) == s_aTests[i].cchPath, ("%s\n", szPath1)); if ( !(u.Parsed.fProps & RTPATH_PROP_EXTRA_SLASHES) && (s_aTests[i].fFlags & RTPATH_STR_F_STYLE_MASK) != RTPATH_STR_F_STYLE_DOS) RTTESTI_CHECK_MSG(strcmp(szPath1, s_aTests[i].pszPath) == 0, ("%s\n", szPath1)); } else RTTestIFailed("RTPathSplitReassemble -> %Rrc", rc); } } }
int main (int argc, char **argv) { #ifndef VBOX RTPrintf("tstSup: SKIPPED\n"); return 0; #else /* * Init. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTR0DbgKrnlInfo", &hTest); if (rc) return rc; RTTestBanner(hTest); uint8_t *pbPage = (uint8_t *)RTTestGuardedAllocTail(hTest, PAGE_SIZE); if (!pbPage) { RTTestFailed(hTest, "RTTestGuardedAllocTail failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } char szPath[RTPATH_MAX]; rc = RTPathExecDir(szPath, sizeof(szPath)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szPath, sizeof(szPath), "tstRTR0DbgKrnlInfo.r0"); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "Failed constructing .r0 filename (rc=%Rrc)", rc); return RTTestSummaryAndDestroy(hTest); } void *pvImageBase; rc = SUPR3LoadServiceModule(szPath, "tstRTR0DbgKrnlInfo", "TSTR0DbgKrnlInfoSrvReqHandler", &pvImageBase); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3LoadServiceModule(%s,,,) failed with rc=%Rrc\n", szPath, rc); return RTTestSummaryAndDestroy(hTest); } /* test request */ struct { SUPR0SERVICEREQHDR Hdr; char szMsg[256]; } Req; /* * Sanity checks. */ RTTestSub(hTest, "Sanity"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstRTR0DbgKrnlInfo", sizeof("tstRTR0DbgKrnlInfo") - 1, TSTRTR0DBGKRNLINFO_SANITY_OK, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(Req.szMsg[0] == '\0', ("%s", Req.szMsg)); if (Req.szMsg[0] != '\0') return RTTestSummaryAndDestroy(hTest); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstRTR0DbgKrnlInfo", sizeof("tstRTR0DbgKrnlInfo") - 1, TSTRTR0DBGKRNLINFO_SANITY_FAILURE, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(!strncmp(Req.szMsg, RT_STR_TUPLE("!42failure42")), ("%s", Req.szMsg)); if (strncmp(Req.szMsg, RT_STR_TUPLE("!42failure42"))) return RTTestSummaryAndDestroy(hTest); /* * Basic tests, bail out on failure. */ RTTestSub(hTest, "Basics"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstRTR0DbgKrnlInfo", sizeof("tstRTR0DbgKrnlInfo") - 1, TSTRTR0DBGKRNLINFO_BASIC, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); if (Req.szMsg[0] == '!') { RTTestIFailed("%s", &Req.szMsg[1]); return RTTestSummaryAndDestroy(hTest); } if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); /* * Done. */ return RTTestSummaryAndDestroy(hTest); #endif }
int main(int argc, char **argv) { #ifndef VBOX RTPrintf("tstSup: SKIPPED\n"); return 0; #else /* * Init. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstR0ThreadPreemption", &hTest); if (rc) return rc; RTTestBanner(hTest); PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3Init failed with rc=%Rrc\n", rc); return RTTestSummaryAndDestroy(hTest); } char szPath[RTPATH_MAX]; rc = RTPathExecDir(szPath, sizeof(szPath)); if (RT_SUCCESS(rc)) rc = RTPathAppend(szPath, sizeof(szPath), "tstR0ThreadPreemption.r0"); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "Failed constructing .r0 filename (rc=%Rrc)", rc); return RTTestSummaryAndDestroy(hTest); } void *pvImageBase; rc = SUPR3LoadServiceModule(szPath, "tstR0ThreadPreemption", "TSTR0ThreadPreemptionSrvReqHandler", &pvImageBase); if (RT_FAILURE(rc)) { RTTestFailed(hTest, "SUPR3LoadServiceModule(%s,,,) failed with rc=%Rrc\n", szPath, rc); return RTTestSummaryAndDestroy(hTest); } /* test request */ struct { SUPR0SERVICEREQHDR Hdr; char szMsg[256]; } Req; /* * Sanity checks. */ RTTestSub(hTest, "Sanity"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_SANITY_OK, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(Req.szMsg[0] == '\0', ("%s", Req.szMsg)); if (Req.szMsg[0] != '\0') return RTTestSummaryAndDestroy(hTest); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_SANITY_FAILURE, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); RTTESTI_CHECK_MSG(!strncmp(Req.szMsg, "!42failure42", sizeof("!42failure42") - 1), ("%s", Req.szMsg)); if (strncmp(Req.szMsg, "!42failure42", sizeof("!42failure42") - 1)) return RTTestSummaryAndDestroy(hTest); /* * Basic tests, bail out on failure. */ RTTestSub(hTest, "Basics"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_BASIC, 0, &Req.Hdr), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); if (Req.szMsg[0] == '!') { RTTestIFailed("%s", &Req.szMsg[1]); return RTTestSummaryAndDestroy(hTest); } if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); /* * Stay in ring-0 until preemption is pending. */ RTThreadSleep(250); /** @todo fix GIP initialization? */ RTTestSub(hTest, "Pending Preemption"); for (int i = 0; ; i++) { Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_IS_PENDING, 0, &Req.Hdr), VINF_SUCCESS); if ( strcmp(Req.szMsg, "cLoops=1\n") || i >= 64) { if (Req.szMsg[0] == '!') RTTestIFailed("%s", &Req.szMsg[1]); else if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); break; } if ((i % 3) == 0) RTThreadYield(); } /* * Test nested RTThreadPreemptDisable calls. */ RTTestSub(hTest, "Nested"); Req.Hdr.u32Magic = SUPR0SERVICEREQHDR_MAGIC; Req.Hdr.cbReq = sizeof(Req); Req.szMsg[0] = '\0'; RTTESTI_CHECK_RC(rc = SUPR3CallR0Service("tstR0ThreadPreemption", sizeof("tstR0ThreadPreemption") - 1, TSTR0THREADPREMEPTION_NESTED, 0, &Req.Hdr), VINF_SUCCESS); if (Req.szMsg[0] == '!') RTTestIFailed("%s", &Req.szMsg[1]); else if (Req.szMsg[0]) RTTestIPrintf(RTTESTLVL_ALWAYS, "%s", Req.szMsg); /* * Done. */ return RTTestSummaryAndDestroy(hTest); #endif }
static 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); }
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 test1Worker(RTTEST hTest, const char *pszBaseDir, const char *pszTarget, RTSYMLINKTYPE enmType, bool fDangling) { char szPath1[RTPATH_MAX]; char szPath2[RTPATH_MAX]; size_t cchTarget = strlen(pszTarget); char szPath3[RTPATH_MAX]; RTStrCopy(szPath3, sizeof(szPath3), pszTarget); #ifdef RT_OS_WINDOWS /* see RTSymlinkCreate in symlink-win.cpp */ char c; char *psz = szPath3; while ((c = *psz) != '\0') { if (c == '/') *psz = '\\'; psz++; } #endif /* Create it.*/ RTTESTI_CHECK_RC_OK_RETV(RTPathJoin(szPath1, sizeof(szPath1), pszBaseDir, "tstRTSymlink-link-1")); RTSymlinkDelete(szPath1, 0); /* clean up previous run */ RTTESTI_CHECK_RC_RETV(RTSymlinkCreate(szPath1, pszTarget, RTSYMLINKTYPE_FILE, 0), VINF_SUCCESS); /* Check the predicate functions. */ RTTESTI_CHECK(RTSymlinkExists(szPath1)); RTTESTI_CHECK(RTSymlinkIsDangling(szPath1) == fDangling); /* Read it. */ memset(szPath2, 0xff, sizeof(szPath2)); szPath2[sizeof(szPath2) - 1] = '\0'; RTTESTI_CHECK_RC(RTSymlinkRead(szPath1, szPath2, sizeof(szPath2), 0), VINF_SUCCESS); RTTESTI_CHECK_MSG(strcmp(szPath2, szPath3) == 0, ("got=\"%s\" expected=\"%s\"", szPath2, szPath3)); memset(szPath2, 0xff, sizeof(szPath2)); szPath2[sizeof(szPath2) - 1] = '\0'; RTTESTI_CHECK_RC(RTSymlinkRead(szPath1, szPath2, cchTarget + 1, 0), VINF_SUCCESS); RTTESTI_CHECK_MSG(strcmp(szPath2, szPath3) == 0, ("got=\"%s\" expected=\"%s\"", szPath2, szPath3)); memset(szPath2, 0xff, sizeof(szPath2)); szPath2[sizeof(szPath2) - 1] = '\0'; RTTESTI_CHECK_RC(RTSymlinkRead(szPath1, szPath2, cchTarget, 0), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK_MSG( strncmp(szPath2, szPath3, cchTarget - 1) == 0 && szPath2[cchTarget - 1] == '\0', ("got=\"%s\" expected=\"%.*s\"", szPath2, cchTarget - 1, szPath3)); /* Other APIs that have to handle symlinks carefully. */ int rc; RTFSOBJINFO ObjInfo; RTTESTI_CHECK_RC(rc = RTPathQueryInfo(szPath1, &ObjInfo, RTFSOBJATTRADD_NOTHING), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)); RTTESTI_CHECK_RC(rc = RTPathQueryInfoEx(szPath1, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)); if (!fDangling) { RTTESTI_CHECK_RC(rc = RTPathQueryInfoEx(szPath1, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(!RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)); else RT_ZERO(ObjInfo); if (enmType == RTSYMLINKTYPE_DIR) { RTTESTI_CHECK(RTDirExists(szPath1)); RTTESTI_CHECK(RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)); } else if (enmType == RTSYMLINKTYPE_FILE) { RTTESTI_CHECK(RTFileExists(szPath1)); RTTESTI_CHECK(RTFS_IS_FILE(ObjInfo.Attr.fMode)); } /** @todo Check more APIs */ } /* Finally, the removal of the symlink. */ RTTESTI_CHECK_RC(RTSymlinkDelete(szPath1, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTSymlinkDelete(szPath1, 0), VERR_FILE_NOT_FOUND); }
int main(int argc, char *argv[]) { /* * Init runtime. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTHeapSimple", &hTest); if (rc) return rc; RTTestBanner(hTest); /* * Create a heap. */ RTTestSub(hTest, "Basics"); static uint8_t s_abMem[128*1024]; RTHEAPSIMPLE Heap; RTTESTI_CHECK_RC(rc = RTHeapSimpleInit(&Heap, &s_abMem[1], sizeof(s_abMem) - 1), VINF_SUCCESS); if (RT_FAILURE(rc)) return RTTestSummaryAndDestroy(hTest); /* * Try allocate. */ static struct TstHeapSimpleOps { size_t cb; unsigned uAlignment; void *pvAlloc; unsigned iFreeOrder; } s_aOps[] = { { 16, 0, NULL, 0 }, // 0 { 16, 4, NULL, 1 }, { 16, 8, NULL, 2 }, { 16, 16, NULL, 5 }, { 16, 32, NULL, 4 }, { 32, 0, NULL, 3 }, // 5 { 31, 0, NULL, 6 }, { 1024, 0, NULL, 8 }, { 1024, 32, NULL, 10 }, { 1024, 32, NULL, 12 }, { PAGE_SIZE, PAGE_SIZE, NULL, 13 }, // 10 { 1024, 32, NULL, 9 }, { PAGE_SIZE, 32, NULL, 11 }, { PAGE_SIZE, PAGE_SIZE, NULL, 14 }, { 16, 0, NULL, 15 }, { 9, 0, NULL, 7 }, // 15 { 16, 0, NULL, 7 }, { 36, 0, NULL, 7 }, { 16, 0, NULL, 7 }, { 12344, 0, NULL, 7 }, { 50, 0, NULL, 7 }, // 20 { 16, 0, NULL, 7 }, }; unsigned i; RTHeapSimpleDump(Heap, (PFNRTHEAPSIMPLEPRINTF)RTPrintf); /** @todo Add some detail info output with a signature identical to RTPrintf. */ size_t cbBefore = RTHeapSimpleGetFreeSize(Heap); static char szFill[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; /* allocate */ for (i = 0; i < RT_ELEMENTS(s_aOps); i++) { s_aOps[i].pvAlloc = RTHeapSimpleAlloc(Heap, s_aOps[i].cb, s_aOps[i].uAlignment); RTTESTI_CHECK_MSG(s_aOps[i].pvAlloc, ("RTHeapSimpleAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i)); if (!s_aOps[i].pvAlloc) return RTTestSummaryAndDestroy(hTest); memset(s_aOps[i].pvAlloc, szFill[i], s_aOps[i].cb); RTTESTI_CHECK_MSG(RT_ALIGN_P(s_aOps[i].pvAlloc, (s_aOps[i].uAlignment ? s_aOps[i].uAlignment : 8)) == s_aOps[i].pvAlloc, ("RTHeapSimpleAlloc(%p, %#x, %#x,) -> %p\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i)); if (!s_aOps[i].pvAlloc) return RTTestSummaryAndDestroy(hTest); } /* free and allocate the same node again. */ for (i = 0; i < RT_ELEMENTS(s_aOps); i++) { if (!s_aOps[i].pvAlloc) continue; //RTPrintf("debug: i=%d pv=%#x cb=%#zx align=%#zx cbReal=%#zx\n", i, s_aOps[i].pvAlloc, // s_aOps[i].cb, s_aOps[i].uAlignment, RTHeapSimpleSize(Heap, s_aOps[i].pvAlloc)); size_t cbBeforeSub = RTHeapSimpleGetFreeSize(Heap); RTHeapSimpleFree(Heap, s_aOps[i].pvAlloc); size_t cbAfterSubFree = RTHeapSimpleGetFreeSize(Heap); void *pv; pv = RTHeapSimpleAlloc(Heap, s_aOps[i].cb, s_aOps[i].uAlignment); RTTESTI_CHECK_MSG(pv, ("RTHeapSimpleAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, s_aOps[i].cb, s_aOps[i].uAlignment, i)); if (!pv) return RTTestSummaryAndDestroy(hTest); //RTPrintf("debug: i=%d pv=%p cbReal=%#zx cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx \n", i, pv, RTHeapSimpleSize(Heap, pv), // cbBeforeSub, cbAfterSubFree, RTHeapSimpleGetFreeSize(Heap)); if (pv != s_aOps[i].pvAlloc) RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: Free+Alloc returned different address. new=%p old=%p i=%d\n", pv, s_aOps[i].pvAlloc, i); s_aOps[i].pvAlloc = pv; size_t cbAfterSubAlloc = RTHeapSimpleGetFreeSize(Heap); if (cbBeforeSub != cbAfterSubAlloc) { RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx. i=%d\n", cbBeforeSub, cbAfterSubFree, cbAfterSubAlloc, i); //return 1; - won't work correctly until we start creating free block instead of donating memory on alignment. } } /* make a copy of the heap and the to-be-freed list. */ static uint8_t s_abMemCopy[sizeof(s_abMem)]; memcpy(s_abMemCopy, s_abMem, sizeof(s_abMem)); uintptr_t offDelta = (uintptr_t)&s_abMemCopy[0] - (uintptr_t)&s_abMem[0]; RTHEAPSIMPLE hHeapCopy = (RTHEAPSIMPLE)((uintptr_t)Heap + offDelta); static struct TstHeapSimpleOps s_aOpsCopy[RT_ELEMENTS(s_aOps)]; memcpy(&s_aOpsCopy[0], &s_aOps[0], sizeof(s_aOps)); /* free it in a specific order. */ int cFreed = 0; for (i = 0; i < RT_ELEMENTS(s_aOps); i++) { unsigned j; for (j = 0; j < RT_ELEMENTS(s_aOps); j++) { if ( s_aOps[j].iFreeOrder != i || !s_aOps[j].pvAlloc) continue; //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapSimpleGetFreeSize(Heap), s_aOps[j].cb, s_aOps[j].pvAlloc); RTHeapSimpleFree(Heap, s_aOps[j].pvAlloc); s_aOps[j].pvAlloc = NULL; cFreed++; } } RTTESTI_CHECK(cFreed == RT_ELEMENTS(s_aOps)); RTTestIPrintf(RTTESTLVL_ALWAYS, "i=done free=%d\n", RTHeapSimpleGetFreeSize(Heap)); /* check that we're back at the right amount of free memory. */ size_t cbAfter = RTHeapSimpleGetFreeSize(Heap); if (cbBefore != cbAfter) { RTTestIPrintf(RTTESTLVL_ALWAYS, "Warning: Either we've split out an alignment chunk at the start, or we've got\n" " an alloc/free accounting bug: cbBefore=%d cbAfter=%d\n", cbBefore, cbAfter); RTHeapSimpleDump(Heap, (PFNRTHEAPSIMPLEPRINTF)RTPrintf); } /* relocate and free the bits in heap2 now. */ RTTestSub(hTest, "RTHeapSimpleRelocate"); rc = RTHeapSimpleRelocate(hHeapCopy, offDelta); RTTESTI_CHECK_RC(rc, VINF_SUCCESS); if (RT_SUCCESS(rc)) { /* free it in a specific order. */ int cFreed2 = 0; for (i = 0; i < RT_ELEMENTS(s_aOpsCopy); i++) { unsigned j; for (j = 0; j < RT_ELEMENTS(s_aOpsCopy); j++) { if ( s_aOpsCopy[j].iFreeOrder != i || !s_aOpsCopy[j].pvAlloc) continue; //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapSimpleGetFreeSize(hHeapCopy), s_aOpsCopy[j].cb, s_aOpsCopy[j].pvAlloc); RTHeapSimpleFree(hHeapCopy, (uint8_t *)s_aOpsCopy[j].pvAlloc + offDelta); s_aOpsCopy[j].pvAlloc = NULL; cFreed2++; } } RTTESTI_CHECK(cFreed2 == RT_ELEMENTS(s_aOpsCopy)); /* check that we're back at the right amount of free memory. */ size_t cbAfterCopy = RTHeapSimpleGetFreeSize(hHeapCopy); RTTESTI_CHECK_MSG(cbAfterCopy == cbAfter, ("cbAfterCopy=%zu cbAfter=%zu\n", cbAfterCopy, cbAfter)); } return RTTestSummaryAndDestroy(hTest); }
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); }
void tstFileAppend1(RTTEST hTest) { /* * Open it write only and do some appending. * Checking that read fails and that the file position changes after the write. */ RTTestSub(hTest, "Basic 1"); RTFileDelete("tstFileAppend-1.tst"); RTFILE hFile = NIL_RTFILE; int rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_NONE | (0644 << RTFILE_O_CREATE_MODE_SHIFT) ); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); uint64_t offActual = 42; uint64_t off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 0 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTESTI_CHECK_RC(RTFileWrite(hFile, "0123456789", 10, NULL), VINF_SUCCESS); offActual = 99; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 10 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after first write\n", offActual); size_t cb = 4; char szBuf[256]; rc = RTFileRead(hFile, szBuf, 1, &cb); RTTESTI_CHECK_MSG(rc == VERR_ACCESS_DENIED || rc == VERR_INVALID_HANDLE, ("rc=%Rrc\n", rc)); offActual = 999; off = 5; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_BEGIN, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 5 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); /* * Open it write only and do some more appending. * Checking the initial position and that it changes after the write. */ RTTestSub(hTest, "Basic 2"); rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_OPEN | RTFILE_O_DENY_NONE ); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); offActual = 99; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 0 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu on 2nd open\n", offActual); RTTESTI_CHECK_RC(rc = RTFileWrite(hFile, "abcdefghij", 10, &cb), VINF_SUCCESS); offActual = 999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 20 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after 2nd write\n", offActual); RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); /* * Open it read/write. * Check the initial position and read stuff. Then append some more and * check the new position and see that read returns 0/EOF. Finally, * do some seeking and read from a new position. */ RTTestSub(hTest, "Basic 3"); rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_READWRITE | RTFILE_O_APPEND | RTFILE_O_OPEN | RTFILE_O_DENY_NONE ); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); offActual = 9; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 0 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu on 3rd open\n", offActual); cb = 99; RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 10, &cb), VINF_SUCCESS); RTTESTI_CHECK(RT_FAILURE(rc) || cb == 10); RTTESTI_CHECK_MSG(RT_FAILURE(rc) || !memcmp(szBuf, "0123456789", 10), ("read the wrong stuff: %.10s - expected 0123456789\n", szBuf)); offActual = 999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 10 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu on 1st open\n", offActual); RTTESTI_CHECK_RC(RTFileWrite(hFile, "klmnopqrst", 10, NULL), VINF_SUCCESS); offActual = 9999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 30 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after 3rd write\n", offActual); RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 1, NULL), VERR_EOF); cb = 99; RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 1, &cb), VINF_SUCCESS); RTTESTI_CHECK(cb == 0); offActual = 99999; off = 15; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_BEGIN, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 15 || RT_FAILURE(rc), ("offActual=%llu", offActual)); if (RT_SUCCESS(rc) && offActual == 15) { RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 10, NULL), VINF_SUCCESS); RTTESTI_CHECK_MSG(RT_FAILURE(rc) || !memcmp(szBuf, "fghijklmno", 10), ("read the wrong stuff: %.10s - expected fghijklmno\n", szBuf)); offActual = 9999999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 25 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after 2nd read\n", offActual); } RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); /* * Open it read only + append and check that we cannot write to it. */ RTTestSub(hTest, "Basic 4"); rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_READ | RTFILE_O_APPEND | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); rc = RTFileWrite(hFile, "pqrstuvwx", 10, &cb); RTTESTI_CHECK_MSG(rc == VERR_ACCESS_DENIED || rc == VERR_INVALID_HANDLE, ("rc=%Rrc\n", rc)); RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); RTTESTI_CHECK_RC(RTFileDelete("tstFileAppend-1.tst"), VINF_SUCCESS); }