tst_QHash: Update the erase_edge_case test

By using the bucketForHash function we can loop through and find
some appropriate keys to test the edge-case. This will then
automatically keep the test working even if some internals
of QHash changes.

We do this because certain changes which change the bucket the
pre-selected keys would end up in could make the test a no-op,
without warning. And recent and upcoming changes have changed
both this and erase(). We limit the search-space to
the minimum numBuckets * 4, where minimum numBuckets is current
128.

Change-Id: I13b0bce15ee884144e3248846be34667fb5d35cc
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Mårten Nordheim 2021-12-14 12:07:36 +01:00 committed by Marc Mutz
parent 9c9cdbedf1
commit 26267ef57e

View File

@ -577,14 +577,40 @@ void tst_QHash::erase()
*/
void tst_QHash::erase_edge_case()
{
QHashSeed::setDeterministicGlobalSeed();
auto resetSeed = qScopeGuard([&]() {
QHashSeed::resetRandomGlobalSeed();
});
QHash<int, int> h1;
h1.reserve(2);
h1.d->seed = 10230148258692185509ull;
h1.insert(3, 4);
h1.insert(5, 6);
qsizetype capacity = h1.capacity();
// Beholden to QHash internals:
qsizetype numBuckets = capacity << 1;
// Find some keys which will both be slotted into the last bucket:
int keys[2];
int index = 0;
for (qsizetype i = 0; i < numBuckets * 4 && index < 2; ++i) {
const size_t hash = qHash(i, QHashSeed::globalSeed());
const size_t bucketForHash = QHashPrivate::GrowthPolicy::bucketForHash(numBuckets, hash);
if (bucketForHash == numBuckets - 1)
keys[index++] = i;
}
QCOMPARE(index, 2); // Sanity check. If this fails then the test needs an update!
// As mentioned earlier these are both calculated to be in the last bucket:
h1.insert(keys[0], 4);
h1.insert(keys[1], 6);
// As a sanity-check, make sure that the key we inserted last is the first one (because its
// allocation to the last bucket would make it wrap around):
// NOTE: If this fails this then this test may need an update!!!
QCOMPARE(h1.constBegin().key(), keys[1]);
// Then we delete the last entry:
QHash<int, int>::iterator it1 = h1.begin();
++it1;
it1 = h1.erase(it1);
// Now, since we deleted the last entry, the iterator should be at the end():
QVERIFY(it1 == h1.end());
}