VirtualBox

Changeset 93684 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Feb 11, 2022 1:23:40 AM (3 years ago)
Author:
vboxsync
Message:

IPRT/hardavl: Fixed the removal bug. Extended testcase and sanity checks. bugref:10093

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/tstRTAvl.cpp

    r93677 r93684  
    3939#include <iprt/string.h>
    4040#include <iprt/test.h>
     41#include <iprt/time.h>
    4142
    4243
     
    10461047
    10471048
     1049static DECLCALLBACK(int) hardAvlRangeTreeGCPhysEnumCallbackCount(TESTNODE *pNode, void *pvUser)
     1050{
     1051    *(uint32_t *)pvUser += 1;
     1052    RT_NOREF(pNode);
     1053    return VINF_SUCCESS;
     1054}
     1055
     1056
    10481057static uint32_t PickClearBit(uint64_t *pbm, uint32_t cItems)
    10491058{
    1050     uint32_t idx = RTRandU32Ex(0, cItems - 1);
     1059    uint32_t idx = RTRandAdvU32Ex(g_hRand, 0, cItems - 1);
    10511060    if (ASMBitTest(pbm, idx) == 0)
    10521061        return idx;
     
    10761085}
    10771086
    1078 #if 0
     1087
    10791088static uint32_t PickSetBit(uint64_t *pbm, uint32_t cItems)
    10801089{
    1081     uint32_t idx = RTRandU32Ex(0, cItems - 1);
     1090    uint32_t idx = RTRandAdvU32Ex(g_hRand, 0, cItems - 1);
    10821091    if (ASMBitTest(pbm, idx) == 1)
    10831092        return idx;
     
    11031112{
    11041113    uint32_t idx = PickSetBit(pbm, cItems);
    1105     RTTESTI_CHECK(ASMBitTestAndSet(pbm, idx) == true);
     1114    RTTESTI_CHECK(ASMBitTestAndClear(pbm, idx) == true);
    11061115    return idx;
    11071116}
    1108 #endif
    1109 
    1110 
    1111 /** @return meaningless, just for return RTTestIFailed(); */
     1117
     1118
     1119/**
     1120 * @return meaningless value, just for shortening 'return RTTestIFailed();'.
     1121 */
    11121122int hardAvlRangeTreeGCPhys(RTTEST hTest)
    11131123{
     
    11231133
    11241134    /* Initialize the allocator with a decent slab of memory. */
    1125     const uint32_t cItems = 16384;
     1135    const uint32_t cItems = 8192;
    11261136    void *pvItems;
    11271137    RTTESTI_CHECK_RC_RET(RTTestGuardedAlloc(hTest, sizeof(MYTESTNODE) * cItems,
     
    11361146     */
    11371147    /* insert */
    1138     for (unsigned i = 0; i < 65536; i += 4)
     1148    for (unsigned i = 0; i < cItems * 4; i += 4)
    11391149    {
    11401150        MYTESTNODE *pNode = Allocator.allocateNode();
     
    11871197
    11881198    /* do gets. */
    1189     for (unsigned i = 0; i < 65536; i += 4)
     1199    for (unsigned i = 0; i < cItems * 4; i += 4)
    11901200    {
    11911201        MYTESTNODE *pNode;
     
    12061216
    12071217    /* negative get */
    1208     for (unsigned i = 65536; i < 65536 * 2; i += 1)
     1218    for (unsigned i = cItems * 4; i < cItems * 4 * 2; i += 1)
    12091219    {
    12101220        MYTESTNODE *pNode = (MYTESTNODE *)(uintptr_t)i;
     
    12231233
    12241234    /* remove */
    1225     for (unsigned i = 0, j = 0; i < 65536; i += 4, j += 3)
     1235    for (unsigned i = 0, j = 0; i < cItems * 4; i += 4, j += 3)
    12261236    {
    12271237        MYTESTNODE *pNode;
     
    12501260    uint64_t uSeed = RTRandU64();
    12511261    RTRandAdvSeed(g_hRand, uSeed);
    1252     RTTestIPrintf(RTTESTLVL_ALWAYS, "Random seed: %#RX64\n", uSeed);
     1262    RTTestIPrintf(RTTESTLVL_ALWAYS, "Random seed #1: %#RX64\n", uSeed);
    12531263
    12541264    RTGCPHYS const   cbStep     = RTGCPHYS_MAX / cItems + 1;
     
    12741284        if (rc != VINF_SUCCESS || pNode2 != pNode)
    12751285            return RTTestIFailed("lookup after random insert %#x: %Rrc pNode=%p pNode2=%p idx=%#x", i, rc, pNode, pNode2, idx);
    1276     }
    1277 
    1278 #if 0 /** @todo this doesn't work quit right yet */
     1286
     1287        uint32_t cCount = 0;
     1288        rc = Tree.doWithAllFromLeft(&Allocator, hardAvlRangeTreeGCPhysEnumCallbackCount, &cCount);
     1289        if (rc != VINF_SUCCESS)
     1290            RTTestIFailed("enum after random insert %#x: %Rrc idx=%#x", i, rc, idx);
     1291        else if (cCount != i + 1)
     1292            RTTestIFailed("wrong count after random removal %#x: %#x, expected %#x", i, cCount, i + 1);
     1293    }
     1294
    12791295    /* remove all in random order. */
    12801296    for (unsigned i = 0; i < cItems; i++)
     
    12861302        if (rc != VINF_SUCCESS)
    12871303            RTTestIFailed("random remove failed: %Rrc, i=%#x, idx=%#x (%RGp ... %RGp)",
    1288                           rc, idx, idx * cbStep, idx * cbStep + cbStep - 1);
    1289         else if (   pNode->Key     != idx * cbStep
     1304                          rc, i, idx, idx * cbStep, idx * cbStep + cbStep - 1);
     1305        else
     1306        {
     1307            if (   pNode->Key     != idx * cbStep
    12901308                 || pNode->KeyLast != idx * cbStep + cbStep - 1)
    1291             RTTestIFailed("random remove returned wrong node: %RGp ... %RGp, expected %RGp ... %RGp (i=%#x, idx=%#x)",
    1292                           pNode->Key, pNode->KeyLast, idx * cbStep, idx * cbStep + cbStep - 1, i, idx);
    1293         else
    1294         {
    1295             MYTESTNODE *pNode2 = (MYTESTNODE *)(intptr_t)i;
    1296             rc = Tree.lookup(&Allocator, idx * cbStep, &pNode2);
    1297             if (rc != VERR_NOT_FOUND)
    1298                 RTTestIFailed("lookup after random removal %#x: %Rrc pNode=%p pNode2=%p idx=%#x", i, rc, pNode, pNode2, idx);
     1309                RTTestIFailed("random remove returned wrong node: %RGp ... %RGp, expected %RGp ... %RGp (i=%#x, idx=%#x)",
     1310                              pNode->Key, pNode->KeyLast, idx * cbStep, idx * cbStep + cbStep - 1, i, idx);
     1311            else
     1312            {
     1313                MYTESTNODE *pNode2 = (MYTESTNODE *)(intptr_t)i;
     1314                rc = Tree.lookup(&Allocator, idx * cbStep, &pNode2);
     1315                if (rc != VERR_NOT_FOUND)
     1316                    RTTestIFailed("lookup after random removal %#x: %Rrc pNode=%p pNode2=%p idx=%#x", i, rc, pNode, pNode2, idx);
     1317
     1318                uint32_t cCount = 0;
     1319                rc = Tree.doWithAllFromLeft(&Allocator, hardAvlRangeTreeGCPhysEnumCallbackCount, &cCount);
     1320                if (rc != VINF_SUCCESS)
     1321                    RTTestIFailed("enum after random removal %#x: %Rrc idx=%#x", i, rc, idx);
     1322                else if (cCount != cItems - i - 1)
     1323                    RTTestIFailed("wrong count after random removal %#x: %#x, expected %#x", i, cCount, cItems - i - 1);
     1324            }
    12991325
    13001326            rc = Allocator.freeNode(pNode);
     
    13031329        }
    13041330    }
    1305 #endif
    1306 
    1307     /** @todo Add more random stuff here where we pick the operation to perform
    1308      *        using random as well and just do large number of these iterations. */
     1331
     1332    /*
     1333     * Randomized operation.
     1334     */
     1335    uSeed = RTRandU64();
     1336    RTRandAdvSeed(g_hRand, uSeed);
     1337    RTTestIPrintf(RTTESTLVL_ALWAYS, "Random seed #2: %#RX64\n", uSeed);
     1338    uint32_t       cInserted    = 0;
     1339    uint64_t       cItemsEnumed = 0;
     1340    bool           fAdding      = true;
     1341    uint64_t const nsStart      = RTTimeNanoTS();
     1342    unsigned       i;
     1343    for (i = 0; i < _64M; i++)
     1344    {
     1345        /* The operation. */
     1346        bool fDelete;
     1347        if (cInserted == cItems)
     1348        {
     1349            fDelete = true;
     1350            fAdding = false;
     1351        }
     1352        else if (cInserted == 0)
     1353        {
     1354            fDelete = false;
     1355            fAdding = true;
     1356        }
     1357        else
     1358            fDelete = fAdding ? RTRandU32Ex(0, 3) == 1 : RTRandU32Ex(0, 3) != 0;
     1359
     1360        if (!fDelete)
     1361        {
     1362            uint32_t const idxInsert = PickClearBitAndSetIt(pbmPresent, cItems);
     1363
     1364            MYTESTNODE *pNode = Allocator.allocateNode();
     1365            if (!pNode)
     1366                return RTTestIFailed("out of nodes: cInserted=%#x cItems=%#x i=%#x", cInserted, cItems, i);
     1367            pNode->Key     = idxInsert * cbStep;
     1368            pNode->KeyLast = pNode->Key + cbStep - 1;
     1369            int rc = Tree.insert(&Allocator, pNode);
     1370            if (rc == VINF_SUCCESS)
     1371                cInserted += 1;
     1372            else
     1373            {
     1374                RTTestIFailed("random insert failed: %Rrc - %RGp ... %RGp cInserted=%#x cItems=%#x i=%#x",
     1375                              rc, pNode->Key, pNode->KeyLast, cInserted, cItems, i);
     1376                Allocator.freeNode(pNode);
     1377            }
     1378        }
     1379        else
     1380        {
     1381            uint32_t const idxDelete = PickSetBitAndClearIt(pbmPresent, cItems);
     1382
     1383            MYTESTNODE *pNode = (MYTESTNODE *)(intptr_t)idxDelete;
     1384            int rc = Tree.remove(&Allocator, idxDelete * cbStep, &pNode);
     1385            if (rc == VINF_SUCCESS)
     1386            {
     1387                if (   pNode->Key     != idxDelete * cbStep
     1388                    || pNode->KeyLast != idxDelete * cbStep + cbStep - 1)
     1389                    RTTestIFailed("random remove returned wrong node: %RGp ... %RGp, expected %RGp ... %RGp (cInserted=%#x cItems=%#x i=%#x)",
     1390                                  pNode->Key, pNode->KeyLast, idxDelete * cbStep, idxDelete * cbStep + cbStep - 1,
     1391                                  cInserted, cItems, i);
     1392
     1393                cInserted -= 1;
     1394                rc = Allocator.freeNode(pNode);
     1395                if (rc != VINF_SUCCESS)
     1396                    RTTestIFailed("free after random removal failed: %Rrc - pNode=%p i=%#x", rc, pNode, i);
     1397            }
     1398            else
     1399                RTTestIFailed("random remove failed: %Rrc - %RGp ... %RGp cInserted=%#x cItems=%#x i=%#x",
     1400                              rc, idxDelete * cbStep, idxDelete * cbStep + cbStep - 1, cInserted, cItems, i);
     1401        }
     1402
     1403        /* Count the tree items.  This will make sure the tree is balanced in strict builds. */
     1404        uint32_t cCount = 0;
     1405        int rc = Tree.doWithAllFromLeft(&Allocator, hardAvlRangeTreeGCPhysEnumCallbackCount, &cCount);
     1406        if (rc != VINF_SUCCESS)
     1407            RTTestIFailed("enum after random %s failed: %Rrc - i=%#x", fDelete ? "removal" : "insert", rc, i);
     1408        else if (cCount != cInserted)
     1409            RTTestIFailed("wrong count after random %s: %#x, expected %#x - i=%#x",
     1410                          cCount, cInserted, fDelete ? "removal" : "insert", i);
     1411        cItemsEnumed += cCount;
     1412
     1413        /* Check for timeout. */
     1414        if (   (i & 0xffff) == 0
     1415            && RTTimeNanoTS() - nsStart >= RT_NS_15SEC)
     1416            break;
     1417    }
     1418    RTTestIPrintf(RTTESTLVL_ALWAYS, "Performed %'u operations and enumerated %'RU64 nodes in %'RU64 ns\n",
     1419                  i, cItemsEnumed, RTTimeNanoTS() - nsStart);
    13091420
    13101421    return 0;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette