/** * Write (output). * * @returns VBox status code. * @param pBack Pointer to the backend structure supplied by * the backend. The backend can use this to find * it's instance data. * @param pvBuf What to write. * @param cbBuf Number of bytes to write. * @param pcbWritten Where to store the number of bytes actually written. * If NULL the entire buffer must be successfully written. */ static DECLCALLBACK(int) tstDBGCBackWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten) { const char *pch = (const char *)pvBuf; if (pcbWritten) *pcbWritten = cbBuf; while (cbBuf-- > 0) { /* screen/log output */ if (g_fPendingPrefix) { RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "OUTPUT: "); g_fPendingPrefix = false; } if (*pch == '\n') g_fPendingPrefix = true; RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "%c", *pch); /* buffer output */ if (g_offOutput < sizeof(g_szOutput) - 1) { g_szOutput[g_offOutput++] = *pch; g_szOutput[g_offOutput] = '\0'; } /* advance */ pch++; } return VINF_SUCCESS; }
/** * Tries one command string. * @param pDbgc Pointer to the debugger instance. * @param pszCmds The command to test. * @param rcCmd The expected result. * @param fNoExecute When set, the command is not executed. * @param pszExpected Expected output. This does not need to include all * of the output, just the start of it. Thus the * prompt can be omitted. */ static void tstTryEx(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected) { RT_ZERO(g_szOutput); g_offOutput = 0; g_pszInput = pszCmds; if (strchr(pszCmds, '\0')[-1] == '\n') RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds); else RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds); pDbgc->rcCmd = VERR_INTERNAL_ERROR; dbgcProcessInput(pDbgc, fNoExecute); tstCompleteOutput(); if (pDbgc->rcCmd != rcCmd) RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd); else if ( !fNoExecute && pszExpected && strncmp(pszExpected, g_szOutput, strlen(pszExpected))) RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected); }
/** * Tries one command string. * @param pDbgc Pointer to the debugger instance. * @param pszCmds The command to test. * @param rcCmd The expected result. * @param fNoExecute When set, the command is not executed. * @param pszExpected Expected output. This does not need to include all * of the output, just the start of it. Thus the * prompt can be omitted. * @param cArgs The number of expected arguments. -1 if we don't * want to check the parsed arguments. * @param va Info about expected parsed arguments. For each * argument a DBGCVARTYPE, value (depends on type), * DBGCVARRANGETYPE and optionally range value. */ static void tstTryExV(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected, int32_t cArgs, va_list va) { RT_ZERO(g_szOutput); g_offOutput = 0; g_pszInput = pszCmds; if (strchr(pszCmds, '\0')[-1] == '\n') RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds); else RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds); pDbgc->rcCmd = VERR_INTERNAL_ERROR; dbgcProcessInput(pDbgc, fNoExecute); tstCompleteOutput(); if (pDbgc->rcCmd != rcCmd) RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd); else if ( !fNoExecute && pszExpected && strncmp(pszExpected, g_szOutput, strlen(pszExpected))) RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected); if (cArgs >= 0) { PCDBGCVAR paArgs = pDbgc->aArgs; for (int32_t iArg = 0; iArg < cArgs; iArg++) { DBGCVAR ExpectedArg; ExpectedArg.enmType = (DBGCVARTYPE)va_arg(va, int/*DBGCVARTYPE*/); switch (ExpectedArg.enmType) { case DBGCVAR_TYPE_GC_FLAT: ExpectedArg.u.GCFlat = va_arg(va, RTGCPTR); break; case DBGCVAR_TYPE_GC_FAR: ExpectedArg.u.GCFar.sel = va_arg(va, int /*RTSEL*/); ExpectedArg.u.GCFar.off = va_arg(va, uint32_t); break; case DBGCVAR_TYPE_GC_PHYS: ExpectedArg.u.GCPhys = va_arg(va, RTGCPHYS); break; case DBGCVAR_TYPE_HC_FLAT: ExpectedArg.u.pvHCFlat = va_arg(va, void *); break; case DBGCVAR_TYPE_HC_PHYS: ExpectedArg.u.HCPhys = va_arg(va, RTHCPHYS); break; case DBGCVAR_TYPE_NUMBER: ExpectedArg.u.u64Number = va_arg(va, uint64_t); break; case DBGCVAR_TYPE_STRING: ExpectedArg.u.pszString = va_arg(va, const char *); break; case DBGCVAR_TYPE_SYMBOL: ExpectedArg.u.pszString = va_arg(va, const char *); break; default: RTTestFailed(g_hTest, "enmType=%u iArg=%u\n", ExpectedArg.enmType, iArg); ExpectedArg.u.u64Number = 0; break; } ExpectedArg.enmRangeType = (DBGCVARRANGETYPE)va_arg(va, int /*DBGCVARRANGETYPE*/); switch (ExpectedArg.enmRangeType) { case DBGCVAR_RANGE_NONE: ExpectedArg.u64Range = 0; break; case DBGCVAR_RANGE_ELEMENTS: ExpectedArg.u64Range = va_arg(va, uint64_t); break; case DBGCVAR_RANGE_BYTES: ExpectedArg.u64Range = va_arg(va, uint64_t); break; default: RTTestFailed(g_hTest, "enmRangeType=%u iArg=%u\n", ExpectedArg.enmRangeType, iArg); ExpectedArg.u64Range = 0; break; } if (!DBGCVarAreIdentical(&ExpectedArg, &paArgs[iArg])) RTTestFailed(g_hTest, "Arg #%u\n" "actual: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n" "expected: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n", iArg, paArgs[iArg].enmType, paArgs[iArg].u.u64Number, paArgs[iArg].enmRangeType, paArgs[iArg].u64Range, ExpectedArg.enmType, ExpectedArg.u.u64Number, ExpectedArg.enmRangeType, ExpectedArg.u64Range); } }
/** * This is called on each EMT and will beat TM. * * @returns VINF_SUCCESS, test failure is reported via RTTEST. * @param pVM Pointer to the VM. * @param hTest The test handle. */ DECLCALLBACK(int) tstTMWorker(PVM pVM, RTTEST hTest) { VMCPUID idCpu = VMMGetCpuId(pVM); RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "idCpu=%d STARTING\n", idCpu); /* * Create the test set. */ int rc; PTMTIMER apTimers[5]; for (size_t i = 0; i < RT_ELEMENTS(apTimers); i++) { rc = TMR3TimerCreateInternal(pVM, i & 1 ? TMCLOCK_VIRTUAL : TMCLOCK_VIRTUAL_SYNC, tstTMDummyCallback, NULL, "test timer", &apTimers[i]); RTTEST_CHECK_RET(hTest, RT_SUCCESS(rc), rc); } /* * The run loop. */ unsigned uPrevPct = 0; uint32_t const cLoops = 100000; for (uint32_t iLoop = 0; iLoop < cLoops; iLoop++) { size_t cLeft = RT_ELEMENTS(apTimers); unsigned i = iLoop % RT_ELEMENTS(apTimers); while (cLeft-- > 0) { PTMTIMER pTimer = apTimers[i]; if ( cLeft == RT_ELEMENTS(apTimers) / 2 && TMTimerIsActive(pTimer)) { rc = TMTimerStop(pTimer); RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerStop: %Rrc\n", rc)); } else { rc = TMTimerSetMicro(pTimer, 50 + cLeft); RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerSetMicro: %Rrc\n", rc)); } /* next */ i = (i + 1) % RT_ELEMENTS(apTimers); } if (i % 3) TMR3TimerQueuesDo(pVM); /* Progress report. */ unsigned uPct = (unsigned)(100.0 * iLoop / cLoops); if (uPct != uPrevPct) { uPrevPct = uPct; if (!(uPct % 10)) RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "idCpu=%d - %3u%%\n", idCpu, uPct); } } RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "idCpu=%d DONE\n", idCpu); return 0; }