File indexing completed on 2025-01-26 10:55:11
0001 /* 0002 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org> 0003 SPDX-FileCopyrightText: 2020 Milian Wolff <mail@milianw.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "lrucachetest.h" 0009 0010 #include <QStandardPaths> 0011 #include <QTest> 0012 #include <QVector> 0013 0014 #include "lrucache.h" 0015 #include <algorithm> 0016 0017 QTEST_GUILESS_MAIN(LRUCacheTest) 0018 0019 LRUCacheTest::LRUCacheTest(QObject *parent) 0020 : QObject(parent) 0021 { 0022 QStandardPaths::setTestModeEnabled(true); 0023 } 0024 0025 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0026 namespace QTest 0027 { 0028 // Why does qtest.h have QList but not QVector support? Oh well, Qt6 unifies that. 0029 template<typename T> 0030 inline bool qCompare(QVector<T> const &t1, QVector<T> const &t2, const char *actual, const char *expected, const char *file, int line) 0031 { 0032 return qCompare(QList<T>(t1.begin(), t1.end()), QList<T>(t2.begin(), t2.end()), actual, expected, file, line); 0033 } 0034 } 0035 #endif 0036 0037 void LRUCacheTest::shouldCacheLastFiveEntries() 0038 { 0039 auto makeString = [](const char *prefix, int i) -> QString { 0040 return QLatin1String(prefix) + QString::number(i); 0041 }; 0042 0043 using Cache = LRUCache<QString, QString>; 0044 Cache cache; 0045 cache.setMaxEntries(5); 0046 auto contents = [&cache]() -> QVector<QString> { 0047 QVector<QString> ret(cache.size()); 0048 std::transform(cache.begin(), cache.end(), ret.begin(), [](const Cache::Entry &entry) { 0049 return entry.value; 0050 }); 0051 return ret; 0052 }; 0053 0054 QCOMPARE(cache.size(), 0); 0055 QCOMPARE(cache.begin(), cache.end()); 0056 QCOMPARE(cache.find(QString()), cache.end()); 0057 0058 QVector<QString> expected; 0059 for (int i = 1; i < 7; ++i) { 0060 const auto expectedSizeBefore = std::min(i - 1, 5); 0061 const auto expectedSizeAfter = std::min(i, 5); 0062 QCOMPARE(cache.size(), expectedSizeBefore); 0063 const auto key = makeString("key", i); 0064 const auto value = makeString("value", i); 0065 QCOMPARE(cache.find(key), cache.end()); 0066 cache.insert(key, value); 0067 QCOMPARE(cache.size(), expectedSizeAfter); 0068 QCOMPARE(std::distance(cache.begin(), cache.find(key)), 0); 0069 QCOMPARE(cache.find(key)->value, value); 0070 expected.prepend(value); 0071 if (expected.size() == 6) { 0072 expected.removeLast(); 0073 } 0074 QCOMPARE(contents(), expected); 0075 } 0076 0077 for (int i = 0; i < 10; ++i) { 0078 const auto key = makeString("key", i); 0079 const auto value = makeString("value", i); 0080 if (i <= 1 || i >= 7) { 0081 QCOMPARE(cache.find(key), cache.end()); 0082 } else { 0083 QCOMPARE(std::distance(cache.begin(), cache.find(key)), 0); 0084 QCOMPARE(cache.find(key)->value, value); 0085 QCOMPARE(value, expected.last()); 0086 expected.removeLast(); 0087 expected.prepend(value); 0088 } 0089 QCOMPARE(contents(), expected); 0090 } 0091 0092 // Looking up an entry moves it the front 0093 auto value = makeString("value", 4); 0094 QCOMPARE(cache.find(makeString("key", 4))->value, value); 0095 QVERIFY(expected.removeOne(value)); 0096 expected.prepend(value); 0097 QCOMPARE(contents(), expected); 0098 0099 // Remove an entry 0100 auto value3 = makeString("value", 3); 0101 QVERIFY(cache.remove(makeString("key", 3))); 0102 QVERIFY(expected.removeOne(value3)); 0103 QCOMPARE(contents(), expected); 0104 0105 cache.clear(); 0106 } 0107 0108 void LRUCacheTest::shouldWorkWithUniquePtr() 0109 { 0110 static int deletions = 0; 0111 struct MyDocument { 0112 ~MyDocument() 0113 { 0114 ++deletions; 0115 } 0116 }; 0117 LRUCache<int, std::unique_ptr<MyDocument>> documentCache; 0118 documentCache.setMaxEntries(32); 0119 documentCache.insert(42, std::make_unique<MyDocument>()); 0120 QCOMPARE(documentCache.size(), 1); 0121 documentCache.clear(); 0122 QCOMPARE(documentCache.size(), 0); 0123 QCOMPARE(deletions, 1); 0124 } 0125 0126 #include "moc_lrucachetest.cpp"