/** * Does a multi-threading list test. Several list additions, reading, replacing * and erasing are done simultaneous. * */ static void test2() { RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); int rc; MTTESTLISTTYPE<MTTESTTYPE> testList; RTTHREAD ahThreads[6]; static PFNRTTHREAD apfnThreads[6] = { MtTest1ThreadProc, MtTest2ThreadProc, MtTest3ThreadProc, MtTest4ThreadProc, MtTest5ThreadProc, MtTest6ThreadProc }; for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) { RTTESTI_CHECK_RC_RETV(RTThreadCreateF(&ahThreads[i], apfnThreads[i], &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest%u", i), VINF_SUCCESS); } uint64_t tsMsDeadline = RTTimeMilliTS() + 60000; for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) { uint64_t tsNow = RTTimeMilliTS(); uint32_t cWait = tsNow > tsMsDeadline ? 5000 : tsMsDeadline - tsNow; RTTESTI_CHECK_RC(RTThreadWait(ahThreads[i], tsNow, NULL), VINF_SUCCESS); } RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); for (size_t i = 0; i < testList.size(); ++i) { uint32_t a = testList.at(i); RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00); } }
static void tstRTCreateProcEx5(const char *pszUser, const char *pszPassword) { RTTestISubF("As user \"%s\" with password \"%s\"", pszUser, pszPassword); const char * apszArgs[3] = { "test", /* user name */ "--testcase-child-5", NULL }; RTPROCESS hProc; /* Test for invalid logons. */ RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, "non-existing-user", "wrong-password", &hProc), VERR_AUTHENTICATION_FAILURE); /* Test for invalid application. */ RTTESTI_CHECK_RC_RETV(RTProcCreateEx("non-existing-app", apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND); /* Test a (hopefully) valid user/password logon (given by parameters of this function). */ RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL, pszUser, pszPassword, &hProc), VINF_SUCCESS); RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND }; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); else RTTestIPassed(NULL); }
/** * Time constrained test with and unlimited N threads. */ static void tst3(uint32_t cThreads, uint32_t cbObject, int iMethod, uint32_t cSecs) { RTTestISubF("Benchmark - %u threads, %u bytes, %u secs, %s", cThreads, cbObject, cSecs, iMethod == 0 ? "RTMemCache" : "RTMemAlloc"); /* * Create a cache with unlimited space, a start semaphore and line up * the threads. */ RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, cbObject, 0 /*cbAlignment*/, UINT32_MAX, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS); RTSEMEVENTMULTI hEvt; RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiCreate(&hEvt)); TST3THREAD aThreads[64]; RTTESTI_CHECK_RETV(cThreads < RT_ELEMENTS(aThreads)); ASMAtomicWriteBool(&g_fTst3Stop, false); for (uint32_t i = 0; i < cThreads; i++) { aThreads[i].hThread = NIL_RTTHREAD; aThreads[i].cIterations = 0; aThreads[i].fUseCache = iMethod == 0; aThreads[i].cbObject = cbObject; aThreads[i].hEvt = hEvt; RTTESTI_CHECK_RC_OK_RETV(RTThreadCreateF(&aThreads[i].hThread, tst3Thread, &aThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst3-%u", i)); } /* * Start the race. */ RTTimeNanoTS(); /* warmup */ uint64_t uStartTS = RTTimeNanoTS(); RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiSignal(hEvt)); RTThreadSleep(cSecs * 1000); ASMAtomicWriteBool(&g_fTst3Stop, true); for (uint32_t i = 0; i < cThreads; i++) RTTESTI_CHECK_RC_OK_RETV(RTThreadWait(aThreads[i].hThread, 60*1000, NULL)); uint64_t cElapsedNS = RTTimeNanoTS() - uStartTS; /* * Sum up the counts. */ uint64_t cIterations = 0; for (uint32_t i = 0; i < cThreads; i++) cIterations += aThreads[i].cIterations; RTTestIPrintf(RTTESTLVL_ALWAYS, "%'8u iterations per second, %'llu ns on avg\n", (unsigned)((long double)cIterations * 1000000000.0 / cElapsedNS), cElapsedNS / cIterations); /* clean up */ RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS); RTTESTI_CHECK_RC_OK(RTSemEventMultiDestroy(hEvt)); }
static void tst1(size_t cTest, size_t cchDigits, char chSep) { RTTestISubF("tst #%u (digits: %u; sep: %c)", cTest, cchDigits, chSep ? chSep : ' '); /* We try to create max possible + one. */ size_t cTimes = 1; for (size_t i = 0; i < cchDigits; ++i) cTimes *= 10; /* Allocate the result array. */ char **papszNames = (char **)RTMemTmpAllocZ(cTimes * sizeof(char *)); RTTESTI_CHECK_RETV(papszNames != NULL); int rc = VERR_INTERNAL_ERROR; /* The test loop. */ size_t i; for (i = 0; i < cTimes; i++) { char szName[RTPATH_MAX]; RTTESTI_CHECK_RC(rc = RTPathAppend(strcpy(szName, g_szTempPath), sizeof(szName), "RTDirCreateUniqueNumbered"), VINF_SUCCESS); if (RT_FAILURE(rc)) break; RTTESTI_CHECK_RC(rc = RTDirCreateUniqueNumbered(szName, sizeof(szName), 0700, cchDigits, chSep), VINF_SUCCESS); if (RT_FAILURE(rc)) { RTTestIFailed("RTDirCreateUniqueNumbered(%s) call #%u -> %Rrc\n", szName, i, rc); break; } RTTESTI_CHECK(papszNames[i] = RTStrDup(szName)); if (!papszNames[i]) break; RTTestIPrintf(RTTESTLVL_DEBUG, "%s\n", papszNames[i]); } /* Try to create one more, which shouldn't be possible. */ if (RT_SUCCESS(rc)) { char szName[RTPATH_MAX]; RTTESTI_CHECK_RC(rc = RTPathAppend(strcpy(szName, g_szTempPath), sizeof(szName), "RTDirCreateUniqueNumbered"), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(rc = RTDirCreateUniqueNumbered(szName, sizeof(szName), 0700, cchDigits, chSep), VERR_ALREADY_EXISTS); } /* cleanup */ while (i-- > 0) { RTTESTI_CHECK_RC(RTDirRemove(papszNames[i]), VINF_SUCCESS); RTStrFree(papszNames[i]); } RTMemTmpFree(papszNames); }
/** * Does a multi-threading list test. Several list additions, reading, replacing * and erasing are done simultaneous. * */ static void test2() { RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); RTTHREAD hThread1, hThread2, hThread3, hThread4, hThread5, hThread6; int rc = VINF_SUCCESS; MTTESTLISTTYPE<MTTESTTYPE> testList; rc = RTThreadCreate(&hThread1, &mttest1, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest1"); AssertRC(rc); rc = RTThreadCreate(&hThread2, &mttest2, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest2"); AssertRC(rc); rc = RTThreadCreate(&hThread3, &mttest3, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest3"); AssertRC(rc); rc = RTThreadCreate(&hThread4, &mttest4, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest4"); AssertRC(rc); rc = RTThreadCreate(&hThread5, &mttest5, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest5"); AssertRC(rc); rc = RTThreadCreate(&hThread6, &mttest6, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest6"); AssertRC(rc); rc = RTThreadWait(hThread1, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread2, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread3, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread4, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread5, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread6, RT_INDEFINITE_WAIT, 0); AssertRC(rc); RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); for (size_t i = 0; i < testList.size(); ++i) { uint32_t a = testList.at(i); RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00); } }
static void testPerformance(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode) { RTTestISubF("Performance - %s", pszSub); size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs; uint64_t cInstrs = 0; uint64_t nsStart = RTTimeNanoTS(); for (uint32_t i = 0; i < _512K; i++) /* the samples are way to small. :-) */ { for (size_t off = 0; off < cbInstrs; cInstrs++) { uint32_t cb = 1; DISSTATE Dis; DISInstrWithReader((uintptr_t)&pabInstrs[off], enmDisCpuMode, testReadBytes, NULL, &Dis, &cb); off += cb; } } uint64_t cNsElapsed = RTTimeNanoTS() - nsStart; RTTestIValueF(cNsElapsed, RTTESTUNIT_NS, "%s-Total", pszSub); RTTestIValueF(cNsElapsed / cInstrs, RTTESTUNIT_NS_PER_CALL, "%s-per-instruction", pszSub); }
/** sub test */ static void tst4Sub(uint32_t cThreads) { RTTestISubF("Serialization - %u threads", cThreads); RTMEMPOOL hMemPool; RTTESTI_CHECK_RC_RETV(RTMemPoolCreate(&hMemPool, "test 2a"), VINF_SUCCESS); g_hMemPool4 = hMemPool; PRTTHREAD pahThreads = (PRTTHREAD)RTMemPoolAlloc(hMemPool, cThreads * sizeof(RTTHREAD)); RTTESTI_CHECK(pahThreads); if (pahThreads) { /* start them. */ for (uint32_t i = 0; i < cThreads; i++) { int rc = RTThreadCreateF(&pahThreads[i], tst4Thread, (void *)(uintptr_t)i, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst4-%u/%u", i, cThreads); RTTESTI_CHECK_RC_OK(rc); if (RT_FAILURE(rc)) pahThreads[i] = NIL_RTTHREAD; } RTThreadYield(); /* kick them off. */ for (uint32_t i = 0; i < cThreads; i++) if (pahThreads[i] != NIL_RTTHREAD) RTTESTI_CHECK_RC_OK(RTThreadUserSignal(pahThreads[i])); /* wait for them. */ for (uint32_t i = 0; i < cThreads; i++) if (pahThreads[i] != NIL_RTTHREAD) { int rc = RTThreadWait(pahThreads[i], 2*60*1000, NULL); RTTESTI_CHECK_RC_OK(rc); } } RTTESTI_CHECK_RC(RTMemPoolDestroy(hMemPool), VINF_SUCCESS); }
static void doTest(PTSTSTATE pThis, uint32_t cbRecv, uint32_t cbSend) { /* * Create an INTNET instance. */ RTTestISub("IntNetR0Init"); RTTESTI_CHECK_RC_RETV(IntNetR0Init(), VINF_SUCCESS); /* * Create two interfaces and activate them. */ RTTestISub("Network creation"); int rc = tstOpenInterfaces(pThis, "test", cbSend, cbRecv); if (RT_FAILURE(rc)) return; RTTESTI_CHECK_RC(IntNetR0IfSetActive(pThis->hIf0, g_pSession, true), VINF_SUCCESS); RTTESTI_CHECK_RC(IntNetR0IfSetActive(pThis->hIf1, g_pSession, true), VINF_SUCCESS); /* * Test basic waiting. */ RTTestISub("IntNetR0IfWait"); RTTESTI_CHECK_RC(IntNetR0IfWait(pThis->hIf0, g_pSession, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC(IntNetR0IfWait(pThis->hIf0, g_pSession, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(IntNetR0IfWait(pThis->hIf1, g_pSession, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC(IntNetR0IfWait(pThis->hIf1, g_pSession, 0), VERR_TIMEOUT); /* * Broadcast send and receive. * (This establishes the MAC address of the 1st interface.) */ RTTestISub("Broadcast"); doBroadcastTest(pThis, false /*fHeadGuard*/); doBroadcastTest(pThis, true /*fHeadGuard*/); /* * Unicast send and receive. * (This establishes the MAC address of the 2nd interface.) */ RTTestISub("Unicast"); doUnicastTest(pThis, false /*fHeadGuard*/); doUnicastTest(pThis, true /*fHeadGuard*/); /* * Do the big bi-directional transfer test if the basics worked out. */ if (!RTTestIErrorCount()) { RTTestISubF("bi-directional benchmark, cbSend=%u, cbRecv=%u, cbTransfer=%u", pThis->pBuf0->cbSend, pThis->pBuf0->cbRecv, g_cbTransfer); tstBidirectionalTransfer(pThis, 256); for (uint32_t cbFrame = 64; cbFrame < cbSend - 64; cbFrame += 8) { RTTestISubF("bi-directional benchmark, cbSend=%u, cbRecv=%u, cbTransfer=%u, cbFrame=%u", pThis->pBuf0->cbSend, pThis->pBuf0->cbRecv, g_cbTransfer, cbFrame); tstBidirectionalTransfer(pThis, cbFrame); } } /* * Destroy the service. */ tstCloseInterfaces(pThis); IntNetR0Term(); }
static void test1(const char *pcszDesc, T3 paTestData[], size_t cTestItems) { RTTestISubF("%s with size of %u (items=%u)", pcszDesc, sizeof(T1), cTestItems); /* * Construction */ /* Create a test list */ L<T1, T2> testList; const size_t defCap = L<T1, T2>::kDefaultCapacity; RTTESTI_CHECK(testList.isEmpty()); RTTESTI_CHECK(testList.size() == 0); RTTESTI_CHECK(testList.capacity() == defCap); /* * Adding */ /* Add the second half of the test data */ size_t cAdded = 1; /* Start adding the second half of our test list */ for (size_t i = cTestItems / 2; i < cTestItems; ++i, ++cAdded) { testList.append(paTestData[i]); RTTESTI_CHECK_RETV(testList.size() == cAdded); RTTESTI_CHECK(testList.at(0) == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList[0] == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList.first() == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[i]); RTTESTI_CHECK(testList[cAdded - 1] == paTestData[i]); RTTESTI_CHECK(testList.last() == paTestData[i]); } /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); RTTESTI_CHECK_RETV(testList.isEmpty() == false); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Start prepending the first half of our test list. Iterate reverse to get * the correct sorting back. */ for (size_t i = cTestItems / 2; i > 0; --i, ++cAdded) { testList.prepend(paTestData[i - 1]); RTTESTI_CHECK_RETV(testList.size() == cAdded); RTTESTI_CHECK(testList.at(0) == paTestData[i - 1]); RTTESTI_CHECK(testList[0] == paTestData[i - 1]); RTTESTI_CHECK(testList.first() == paTestData[i - 1]); RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[cTestItems - 1]); RTTESTI_CHECK(testList[cAdded - 1] == paTestData[cTestItems - 1]); RTTESTI_CHECK(testList.last() == paTestData[cTestItems - 1]); } /* Check that all is correctly prepended. */ RTTESTI_CHECK_RETV(testList.size() == cTestItems); RTTESTI_CHECK_RETV(testList.isEmpty() == false); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[i]); /* * Contains */ L<T1, T2> testList2; /* Check full list. */ RTTESTI_CHECK( testList.contains(paTestData[0])); RTTESTI_CHECK( testList.contains(paTestData[cTestItems / 2])); RTTESTI_CHECK( testList.contains(paTestData[cTestItems - 1])); RTTESTI_CHECK(!testList.contains(T1())); /* Check empty list. */ RTTESTI_CHECK(!testList2.contains(paTestData[0])); RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems / 2])); RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems - 1])); RTTESTI_CHECK(!testList2.contains(T1())); /* * Copy operator */ L<T1, T2> testList3(testList); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i]); /* * "=" operator */ L<T1, T2> testList4; testList4 = testList; /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList4.size() == cTestItems); for (size_t i = 0; i < testList4.size(); ++i) RTTESTI_CHECK(testList4.at(i) == paTestData[i]); /* * Append list */ testList3.append(testList4); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* * Prepend list */ testList3.prepend(testList4); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 3); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* * "value" method */ for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.value(i) == paTestData[i % cTestItems]); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.value(i, T1()) == paTestData[i % cTestItems]); RTTESTI_CHECK(testList3.value(testList3.size() + 1) == T1()); /* Invalid index */ RTTESTI_CHECK(testList3.value(testList3.size() + 1, T1()) == T1()); /* Invalid index */ /* * operator[] (reading) */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[i]); /* * operator[] (writing) * * Replace with inverted array. */ for (size_t i = 0; i < cTestItems; ++i) testList[i] = paTestData[cTestItems - i - 1]; RTTESTI_CHECK_RETV(testList.size() == cTestItems); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[cTestItems - i - 1]); /* * Replace * * Replace with inverted array (Must be original array when finished). */ for (size_t i = 0; i < cTestItems; ++i) testList.replace(i, paTestData[i]); RTTESTI_CHECK_RETV(testList.size() == cTestItems); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[i]); /* * Removing */ /* Remove Range */ testList3.removeRange(cTestItems, cTestItems * 2); RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* Remove the first half (reverse) */ size_t cRemoved = 1; for (size_t i = cTestItems / 2; i > 0; --i, ++cRemoved) { testList.removeAt(i - 1); RTTESTI_CHECK_RETV(testList.size() == cTestItems - cRemoved); } RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); /* Check that all is correctly removed and only the second part of the list * is still there. */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* * setCapacitiy */ testList.setCapacity(cTestItems * 5); RTTESTI_CHECK(testList.capacity() == cTestItems * 5); RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); /* As the capacity just increased, we should still have all entries from * the previous list. */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Decrease the capacity so it will be smaller than the count of items in * the list. The list should be shrink automatically, but the remaining * items should be still valid. */ testList.setCapacity(cTestItems / 4); RTTESTI_CHECK_RETV(testList.size() == cTestItems / 4); RTTESTI_CHECK(testList.capacity() == cTestItems / 4); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Clear all */ testList.clear(); RTTESTI_CHECK_RETV(testList.isEmpty()); RTTESTI_CHECK_RETV(testList.size() == 0); RTTESTI_CHECK(testList.capacity() == defCap); /* Copy empty lists. */ L<T1, T2> testList5(testList); RTTESTI_CHECK_RETV(testList5.isEmpty()); RTTESTI_CHECK_RETV(testList5.size() == 0); RTTESTI_CHECK(testList5.capacity() == 0); testList5.append(paTestData[0]); testList5 = testList; RTTESTI_CHECK_RETV(testList5.isEmpty()); RTTESTI_CHECK_RETV(testList5.size() == 0); RTTESTI_CHECK(testList5.capacity() == 0); /* * Negative testing. */ bool fMayPanic = RTAssertMayPanic(); bool fQuiet = RTAssertAreQuiet(); RTAssertSetMayPanic(false); RTAssertSetQuiet(true); L<T1, T2> testList6; for (size_t i = 0; i < cTestItems; ++i) testList6.insert(i, paTestData[i]); RTTESTI_CHECK(testList6.size() == cTestItems); /* Insertion beyond the end of the array ends up at the end. */ size_t cBefore = testList6.size(); testList6.insert(cBefore + 3, paTestData[0]); RTTESTI_CHECK(testList6.size() == cBefore + 1); RTTESTI_CHECK(testList6.at(cBefore) == paTestData[0]); cBefore = testList6.size(); L<T1, T2> testList7(testList6); testList6.insert(testList6.size() + 42, testList7); RTTESTI_CHECK(testList6.size() == cBefore + testList7.size()); /* Inserting, appending or prepending a list to itself is not supported. */ cBefore = testList6.size(); testList6.insert(3, testList6); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.append(testList6); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.prepend(testList6); RTTESTI_CHECK(testList6.size() == cBefore); /* Replace does nothing if the index is bad. */ cBefore = testList6.size(); testList6.replace(cBefore, testList6[6]); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.replace(cBefore + 64, testList6[6]); RTTESTI_CHECK(testList6.size() == cBefore); /* Indexing beyond the array returns the last element. */ cBefore = testList6.size(); RTTESTI_CHECK(testList6[cBefore] == testList6.last()); RTTESTI_CHECK(testList6[cBefore + 42] == testList6.last()); RTTESTI_CHECK(&testList6[cBefore] == &testList6[cBefore - 1]); RTTESTI_CHECK(&testList6[cBefore + 42] == &testList6[cBefore - 1]); /* removeAt does nothing if the index is bad. */ cBefore = testList6.size(); testList6.removeAt(cBefore); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeAt(cBefore + 42); RTTESTI_CHECK(testList6.size() == cBefore); L<T1, T2> testListEmpty1; RTTESTI_CHECK(!testListEmpty1.size()); testListEmpty1.removeFirst(); RTTESTI_CHECK(!testListEmpty1.size()); testListEmpty1.removeLast(); RTTESTI_CHECK(!testListEmpty1.size()); testListEmpty1.removeAt(128); RTTESTI_CHECK(!testListEmpty1.size()); /* removeRange interprets indexes beyond the end as the end of array (asserted). */ testListEmpty1.removeRange(42, 128); RTTESTI_CHECK(!testListEmpty1.size()); cBefore = testList6.size(); testList6.removeRange(cBefore, cBefore); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeRange(cBefore + 12, cBefore + 128); RTTESTI_CHECK(testList6.size() == cBefore); /* If end is less or equal to the start, nothing is done. */ testListEmpty1.removeRange(128, 0); RTTESTI_CHECK(!testListEmpty1.size()); cBefore = testList6.size(); testList6.removeRange(cBefore, 0); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeRange(0, 0); RTTESTI_CHECK(testList6.size() == cBefore); cBefore = testList6.size(); testList6.removeRange(0, 0); RTTESTI_CHECK(testList6.size() == cBefore); RTAssertSetQuiet(fQuiet); RTAssertSetMayPanic(fMayPanic); }
static void test1(const char *pcszDesc, T3 paTestData[], size_t cTestItems) { RTTestISubF("%s with size of %u (items=%u)", pcszDesc, sizeof(T1), cTestItems); /* * Construction */ /* Create a test list */ L<T1, T2> testList; const size_t defCap = L<T1, T2>::DefaultCapacity; RTTESTI_CHECK(testList.isEmpty()); RTTESTI_CHECK(testList.size() == 0); RTTESTI_CHECK(testList.capacity() == defCap); /* * Adding */ /* Add the second half of the test data */ size_t cAdded = 1; /* Start adding the second half of our test list */ for (size_t i = cTestItems / 2; i < cTestItems; ++i, ++cAdded) { testList.append(paTestData[i]); RTTESTI_CHECK_RETV(testList.size() == cAdded); RTTESTI_CHECK(testList.at(0) == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList[0] == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList.first() == paTestData[cTestItems / 2]); RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[i]); RTTESTI_CHECK(testList[cAdded - 1] == paTestData[i]); RTTESTI_CHECK(testList.last() == paTestData[i]); } /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); RTTESTI_CHECK_RETV(testList.isEmpty() == false); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Start prepending the first half of our test list. Iterate reverse to get * the correct sorting back. */ for (size_t i = cTestItems / 2; i > 0; --i, ++cAdded) { testList.prepend(paTestData[i - 1]); RTTESTI_CHECK_RETV(testList.size() == cAdded); RTTESTI_CHECK(testList.at(0) == paTestData[i - 1]); RTTESTI_CHECK(testList[0] == paTestData[i - 1]); RTTESTI_CHECK(testList.first() == paTestData[i - 1]); RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[cTestItems - 1]); RTTESTI_CHECK(testList[cAdded - 1] == paTestData[cTestItems - 1]); RTTESTI_CHECK(testList.last() == paTestData[cTestItems - 1]); } /* Check that all is correctly prepended. */ RTTESTI_CHECK_RETV(testList.size() == cTestItems); RTTESTI_CHECK_RETV(testList.isEmpty() == false); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[i]); /* * Contains */ L<T1, T2> testList2; /* Check full list. */ RTTESTI_CHECK( testList.contains(paTestData[0])); RTTESTI_CHECK( testList.contains(paTestData[cTestItems / 2])); RTTESTI_CHECK( testList.contains(paTestData[cTestItems - 1])); RTTESTI_CHECK(!testList.contains(T1())); /* Check empty list. */ RTTESTI_CHECK(!testList2.contains(paTestData[0])); RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems / 2])); RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems - 1])); RTTESTI_CHECK(!testList2.contains(T1())); /* * Copy operator */ L<T1, T2> testList3(testList); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i]); /* * "=" operator */ L<T1, T2> testList4; testList4 = testList; /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList4.size() == cTestItems); for (size_t i = 0; i < testList4.size(); ++i) RTTESTI_CHECK(testList4.at(i) == paTestData[i]); /* * Append list */ testList3.append(testList4); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* * Prepend list */ testList3.prepend(testList4); /* Check that all is correctly appended. */ RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 3); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* * "value" method */ for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.value(i) == paTestData[i % cTestItems]); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.value(i, T1()) == paTestData[i % cTestItems]); RTTESTI_CHECK(testList3.value(testList3.size() + 1) == T1()); /* Invalid index */ RTTESTI_CHECK(testList3.value(testList3.size() + 1, T1()) == T1()); /* Invalid index */ /* * operator[] (reading) */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[i]); /* * operator[] (writing) * * Replace with inverted array. */ for (size_t i = 0; i < cTestItems; ++i) testList[i] = paTestData[cTestItems - i - 1]; RTTESTI_CHECK_RETV(testList.size() == cTestItems); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[cTestItems - i - 1]); /* * Replace * * Replace with inverted array (Must be original array when finished). */ for (size_t i = 0; i < cTestItems; ++i) testList.replace(i, paTestData[i]); RTTESTI_CHECK_RETV(testList.size() == cTestItems); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList[i] == paTestData[i]); /* * Removing */ /* Remove Range */ testList3.removeRange(cTestItems, cTestItems * 2); RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2); for (size_t i = 0; i < testList3.size(); ++i) RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]); /* Remove the first half (reverse) */ size_t cRemoved = 1; for (size_t i = cTestItems / 2; i > 0; --i, ++cRemoved) { testList.removeAt(i - 1); RTTESTI_CHECK_RETV(testList.size() == cTestItems - cRemoved); } RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); /* Check that all is correctly removed and only the second part of the list * is still there. */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* * setCapacitiy */ testList.setCapacity(cTestItems * 5); RTTESTI_CHECK(testList.capacity() == cTestItems * 5); RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2); /* As the capacity just increased, we should still have all entries from * the previous list. */ for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Decrease the capacity so it will be smaller than the count of items in * the list. The list should be shrink automatically, but the remaining * items should be still valid. */ testList.setCapacity(cTestItems / 4); RTTESTI_CHECK_RETV(testList.size() == cTestItems / 4); RTTESTI_CHECK(testList.capacity() == cTestItems / 4); for (size_t i = 0; i < testList.size(); ++i) RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]); /* Clear all */ testList.clear(); RTTESTI_CHECK_RETV(testList.isEmpty()); RTTESTI_CHECK_RETV(testList.size() == 0); RTTESTI_CHECK(testList.capacity() == defCap); /* Copy empty lists. */ L<T1, T2> testList5(testList); RTTESTI_CHECK_RETV(testList5.isEmpty()); RTTESTI_CHECK_RETV(testList5.size() == 0); RTTESTI_CHECK(testList5.capacity() == 0); testList5.append(paTestData[0]); testList5 = testList; RTTESTI_CHECK_RETV(testList5.isEmpty()); RTTESTI_CHECK_RETV(testList5.size() == 0); RTTESTI_CHECK(testList5.capacity() == 0); }