File indexing completed on 2025-01-19 13:24:02

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"