mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-04 08:15:30 +08:00
6.5.3 clean
This commit is contained in:
@ -7,12 +7,16 @@
|
||||
#include <qpixmapcache.h>
|
||||
#include "private/qpixmapcache_p.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
QT_BEGIN_NAMESPACE // The test requires QT_BUILD_INTERNAL
|
||||
Q_AUTOTEST_EXPORT void qt_qpixmapcache_flush_detached_pixmaps();
|
||||
Q_AUTOTEST_EXPORT int qt_qpixmapcache_qpixmapcache_total_used();
|
||||
Q_AUTOTEST_EXPORT int q_QPixmapCache_keyHashSize();
|
||||
QT_END_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
class tst_QPixmapCache : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -29,13 +33,20 @@ private slots:
|
||||
void setCacheLimit();
|
||||
void find();
|
||||
void insert();
|
||||
void failedInsertReturnsInvalidKey();
|
||||
void replace();
|
||||
void remove();
|
||||
void clear();
|
||||
void pixmapKey();
|
||||
void noLeak();
|
||||
void clearDoesNotLeakStringKeys();
|
||||
void evictionDoesNotLeakStringKeys();
|
||||
void reducingCacheLimitDoesNotLeakStringKeys();
|
||||
void strictCacheLimit();
|
||||
void noCrashOnLargeInsert();
|
||||
|
||||
private:
|
||||
void stringLeak_impl(std::function<void()> whenOp);
|
||||
};
|
||||
|
||||
static QPixmapCache::KeyData* getPrivate(QPixmapCache::Key &key)
|
||||
@ -102,16 +113,16 @@ void tst_QPixmapCache::setCacheLimit()
|
||||
//The int part of the API
|
||||
p1 = new QPixmap(2, 3);
|
||||
QPixmapCache::Key key = QPixmapCache::insert(*p1);
|
||||
QVERIFY(QPixmapCache::find(key, p1) != 0);
|
||||
QVERIFY(QPixmapCache::find(key, p1));
|
||||
delete p1;
|
||||
|
||||
QPixmapCache::setCacheLimit(0);
|
||||
QVERIFY(QPixmapCache::find(key, p1) == 0);
|
||||
QVERIFY(!QPixmapCache::find(key, p1));
|
||||
|
||||
p1 = new QPixmap(2, 3);
|
||||
QPixmapCache::setCacheLimit(1000);
|
||||
QPixmapCache::replace(key, *p1);
|
||||
QVERIFY(QPixmapCache::find(key, p1) == 0);
|
||||
p1 = new QPixmap(2, 3);
|
||||
QVERIFY(!QPixmapCache::replace(key, *p1));
|
||||
QVERIFY(!QPixmapCache::find(key, p1));
|
||||
|
||||
delete p1;
|
||||
|
||||
@ -120,10 +131,10 @@ void tst_QPixmapCache::setCacheLimit()
|
||||
QPixmapCache::clear();
|
||||
p1 = new QPixmap(2, 3);
|
||||
key = QPixmapCache::insert(*p1);
|
||||
QVERIFY(QPixmapCache::find(key, p1) != 0);
|
||||
QVERIFY(QPixmapCache::find(key, p1));
|
||||
p1->detach(); // dectach so that the cache thinks no-one is using it.
|
||||
QPixmapCache::setCacheLimit(0);
|
||||
QVERIFY(QPixmapCache::find(key, p1) == 0);
|
||||
QVERIFY(!QPixmapCache::find(key, p1));
|
||||
QPixmapCache::setCacheLimit(1000);
|
||||
key = QPixmapCache::insert(*p1);
|
||||
QVERIFY(key.isValid());
|
||||
@ -137,7 +148,7 @@ void tst_QPixmapCache::setCacheLimit()
|
||||
QPixmap p2;
|
||||
p1 = new QPixmap(2, 3);
|
||||
key = QPixmapCache::insert(*p1);
|
||||
QVERIFY(QPixmapCache::find(key, &p2) != 0);
|
||||
QVERIFY(QPixmapCache::find(key, &p2));
|
||||
//we flush the cache
|
||||
p1->detach();
|
||||
p2.detach();
|
||||
@ -145,8 +156,8 @@ void tst_QPixmapCache::setCacheLimit()
|
||||
QPixmapCache::setCacheLimit(1000);
|
||||
QPixmapCache::Key key2 = QPixmapCache::insert(*p1);
|
||||
QCOMPARE(getPrivate(key2)->key, 1);
|
||||
QVERIFY(QPixmapCache::find(key, &p2) == 0);
|
||||
QVERIFY(QPixmapCache::find(key2, &p2) != 0);
|
||||
QVERIFY(!QPixmapCache::find(key, &p2));
|
||||
QVERIFY(QPixmapCache::find(key2, &p2));
|
||||
QCOMPARE(p2, *p1);
|
||||
|
||||
delete p1;
|
||||
@ -169,7 +180,7 @@ void tst_QPixmapCache::setCacheLimit()
|
||||
QCOMPARE(getPrivate(key2)->key, 1);
|
||||
//This old key is not valid anymore after the flush
|
||||
QVERIFY(!key.isValid());
|
||||
QVERIFY(QPixmapCache::find(key, &p2) == 0);
|
||||
QVERIFY(!QPixmapCache::find(key, &p2));
|
||||
delete p1;
|
||||
}
|
||||
|
||||
@ -207,7 +218,7 @@ void tst_QPixmapCache::find()
|
||||
QPixmapCache::insert(p5);
|
||||
|
||||
//at that time the first key has been erase because no more place in the cache
|
||||
QVERIFY(QPixmapCache::find(key, &p1) == 0);
|
||||
QVERIFY(!QPixmapCache::find(key, &p1));
|
||||
QVERIFY(!key.isValid());
|
||||
}
|
||||
|
||||
@ -266,6 +277,7 @@ void tst_QPixmapCache::insert()
|
||||
for (int i = 0; i < numberOfKeys; ++i) {
|
||||
QPixmap p3(10,10);
|
||||
keys.append(QPixmapCache::insert(p3));
|
||||
QVERIFY(keys.back().isValid());
|
||||
}
|
||||
|
||||
num = 0;
|
||||
@ -279,6 +291,32 @@ void tst_QPixmapCache::insert()
|
||||
QVERIFY(num <= estimatedNum);
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::failedInsertReturnsInvalidKey()
|
||||
{
|
||||
//
|
||||
// GIVEN: a pixmap whose memory footprint exceeds the cache's limit:
|
||||
//
|
||||
QPixmapCache::setCacheLimit(20);
|
||||
|
||||
QPixmap pm(256, 256);
|
||||
pm.fill(Qt::transparent);
|
||||
QCOMPARE_GT(pm.width() * pm.height() * pm.depth() / 8,
|
||||
QPixmapCache::cacheLimit() * 1024);
|
||||
|
||||
//
|
||||
// WHEN: trying to add this pixmap to the cache
|
||||
//
|
||||
const auto success = QPixmapCache::insert(u"foo"_s, pm); // QString API
|
||||
{ QPixmap r; QVERIFY(!QPixmapCache::find(u"foo"_s, &r)); }
|
||||
const auto key = QPixmapCache::insert(pm); // "int" API
|
||||
|
||||
//
|
||||
// THEN: failure is reported to the user
|
||||
//
|
||||
QVERIFY(!key.isValid()); // "int" API
|
||||
QVERIFY(!success); // QString API
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::replace()
|
||||
{
|
||||
//The int part of the API
|
||||
@ -340,11 +378,11 @@ void tst_QPixmapCache::remove()
|
||||
QVERIFY(p1.toImage() == p1.toImage()); // sanity check
|
||||
|
||||
QPixmapCache::remove(key);
|
||||
QVERIFY(QPixmapCache::find(key, &p1) == 0);
|
||||
QVERIFY(!QPixmapCache::find(key, &p1));
|
||||
|
||||
//Broken key
|
||||
QPixmapCache::remove(QPixmapCache::Key());
|
||||
QVERIFY(QPixmapCache::find(QPixmapCache::Key(), &p1) == 0);
|
||||
QVERIFY(!QPixmapCache::find(QPixmapCache::Key(), &p1));
|
||||
|
||||
//Test if keys are release
|
||||
QPixmapCache::clear();
|
||||
@ -358,7 +396,7 @@ void tst_QPixmapCache::remove()
|
||||
QPixmapCache::clear();
|
||||
key = QPixmapCache::insert(p1);
|
||||
QCOMPARE(getPrivate(key)->key, 1);
|
||||
QVERIFY(QPixmapCache::find(key, &p1) != 0);
|
||||
QVERIFY(QPixmapCache::find(key, &p1));
|
||||
QPixmapCache::remove(key);
|
||||
QCOMPARE(p1.isDetached(), true);
|
||||
|
||||
@ -368,8 +406,8 @@ void tst_QPixmapCache::remove()
|
||||
QPixmapCache::insert("red", p1);
|
||||
key = QPixmapCache::insert(p1);
|
||||
QPixmapCache::remove(key);
|
||||
QVERIFY(QPixmapCache::find(key, &p1) == 0);
|
||||
QVERIFY(QPixmapCache::find("red", &p1) != 0);
|
||||
QVERIFY(!QPixmapCache::find(key, &p1));
|
||||
QVERIFY(QPixmapCache::find("red", &p1));
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::clear()
|
||||
@ -413,7 +451,7 @@ void tst_QPixmapCache::clear()
|
||||
QPixmapCache::clear();
|
||||
|
||||
for (int k = 0; k < numberOfKeys; ++k) {
|
||||
QVERIFY(QPixmapCache::find(keys.at(k), &p1) == 0);
|
||||
QVERIFY(!QPixmapCache::find(keys.at(k), &p1));
|
||||
QVERIFY(!keys[k].isValid());
|
||||
}
|
||||
}
|
||||
@ -478,6 +516,68 @@ void tst_QPixmapCache::noLeak()
|
||||
QCOMPARE(oldSize, newSize);
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::clearDoesNotLeakStringKeys()
|
||||
{
|
||||
stringLeak_impl([] { QPixmapCache::clear(); });
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::evictionDoesNotLeakStringKeys()
|
||||
{
|
||||
stringLeak_impl([] {
|
||||
// fill the cache with other pixmaps to force eviction of "our" pixmap:
|
||||
constexpr int Iterations = 10;
|
||||
for (int i = 0; i < Iterations; ++i) {
|
||||
QPixmap pm(64, 64);
|
||||
pm.fill(Qt::transparent);
|
||||
[[maybe_unused]] auto r = QPixmapCache::insert(pm);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::reducingCacheLimitDoesNotLeakStringKeys()
|
||||
{
|
||||
stringLeak_impl([] {
|
||||
QPixmapCache::setCacheLimit(0);
|
||||
});
|
||||
}
|
||||
|
||||
void tst_QPixmapCache::stringLeak_impl(std::function<void()> whenOp)
|
||||
{
|
||||
QVERIFY(whenOp);
|
||||
|
||||
QPixmapCache::setCacheLimit(20); // 20KiB
|
||||
//
|
||||
// GIVEN: a QPixmap with QString key `key` in QPixmapCache
|
||||
//
|
||||
QString key;
|
||||
{
|
||||
QPixmap pm(64, 64);
|
||||
QCOMPARE_LT(pm.width() * pm.height() * std::ceil(pm.depth() / 8.0),
|
||||
QPixmapCache::cacheLimit() * 1024);
|
||||
pm.fill(Qt::transparent);
|
||||
key = u"theKey"_s.repeated(20); // avoid eventual QString SSO
|
||||
QVERIFY(key.isDetached());
|
||||
QPixmapCache::insert(key, pm);
|
||||
}
|
||||
QVERIFY(!key.isDetached()); // was saved inside QPixmapCache
|
||||
|
||||
//
|
||||
// WHEN: performing the given operation
|
||||
//
|
||||
whenOp();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
//
|
||||
// THEN: `key` is no longer referenced by QPixmapCache:
|
||||
//
|
||||
QVERIFY(key.isDetached());
|
||||
// verify that the pixmap is really gone from the cache
|
||||
// (do it after the key check, because QPixmapCache cleans up `key` on a failed lookup)
|
||||
QPixmap r;
|
||||
QVERIFY(!QPixmapCache::find(key, &r));
|
||||
}
|
||||
|
||||
|
||||
void tst_QPixmapCache::strictCacheLimit()
|
||||
{
|
||||
|
Reference in New Issue
Block a user