File indexing completed on 2024-05-12 17:09:49

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "../history.h"
0008 #include "../historystringitem.h"
0009 // Qt
0010 #include <QObject>
0011 #include <QSignalSpy>
0012 #include <QtTest>
0013 
0014 class HistoryTest : public QObject
0015 {
0016     Q_OBJECT
0017 private Q_SLOTS:
0018     void testSetMaxSize();
0019     void testInsertRemove();
0020     void testClear();
0021     void testFind();
0022     void testCycle();
0023 };
0024 
0025 void HistoryTest::testSetMaxSize()
0026 {
0027     std::unique_ptr<History> history(new History(nullptr));
0028     QSignalSpy changedSpy(history.get(), &History::changed);
0029     QSignalSpy topSpy(history.get(), &History::topChanged);
0030     QVERIFY(history->empty());
0031     QCOMPARE(history->maxSize(), 0u);
0032     QVERIFY(changedSpy.isEmpty());
0033     QVERIFY(topSpy.isEmpty());
0034 
0035     // insert an item - should still be empty
0036     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("foo"))));
0037     QVERIFY(history->empty());
0038     QVERIFY(changedSpy.isEmpty());
0039     QVERIFY(topSpy.isEmpty());
0040 
0041     // now it should insert again
0042     history->setMaxSize(1);
0043     QCOMPARE(history->maxSize(), 1u);
0044     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("foo"))));
0045     QVERIFY(!history->empty());
0046     QCOMPARE(changedSpy.size(), 1);
0047     changedSpy.clear();
0048     QVERIFY(changedSpy.isEmpty());
0049     QCOMPARE(topSpy.size(), 1);
0050     topSpy.clear();
0051     QVERIFY(topSpy.isEmpty());
0052 
0053     // insert another item, foo should get removed
0054     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("bar"))));
0055     QCOMPARE(history->first()->text(), QLatin1String("bar"));
0056     QCOMPARE(history->first()->next_uuid(), history->first()->uuid());
0057     QCOMPARE(topSpy.size(), 1);
0058     topSpy.clear();
0059     QVERIFY(topSpy.isEmpty());
0060     // two changed events - once added, once removed
0061     QCOMPARE(changedSpy.size(), 2);
0062     changedSpy.clear();
0063     QVERIFY(changedSpy.isEmpty());
0064 
0065     // setting to 0 should clear again
0066     history->setMaxSize(0);
0067     QCOMPARE(history->maxSize(), 0u);
0068     QVERIFY(history->empty());
0069     QCOMPARE(changedSpy.size(), 1);
0070     QCOMPARE(topSpy.size(), 1);
0071 }
0072 
0073 void HistoryTest::testInsertRemove()
0074 {
0075     std::unique_ptr<History> history(new History(nullptr));
0076     QSignalSpy topSpy(history.get(), &History::topChanged);
0077     QSignalSpy topUserSelectedSpy(history.get(), &History::topIsUserSelectedSet);
0078 
0079     history->setMaxSize(10);
0080     QVERIFY(history->empty());
0081     QVERIFY(!history->topIsUserSelected());
0082 
0083     const QString fooText = QStringLiteral("foo");
0084     const QString barText = QStringLiteral("bar");
0085     const QString fooBarText = QStringLiteral("foobar");
0086     const QByteArray fooUuid = QCryptographicHash::hash(fooText.toUtf8(), QCryptographicHash::Sha1);
0087     const QByteArray barUuid = QCryptographicHash::hash(barText.toUtf8(), QCryptographicHash::Sha1);
0088     const QByteArray foobarUuid = QCryptographicHash::hash(fooBarText.toUtf8(), QCryptographicHash::Sha1);
0089 
0090     // let's insert a few items
0091     history->insert(HistoryItemPtr(new HistoryStringItem(fooText)));
0092     QVERIFY(!history->topIsUserSelected());
0093     QCOMPARE(history->first()->text(), fooText);
0094     QCOMPARE(history->first()->next_uuid(), history->first()->uuid());
0095     QCOMPARE(history->first()->previous_uuid(), history->first()->uuid());
0096     QCOMPARE(topSpy.size(), 1);
0097     topSpy.clear();
0098     QVERIFY(topSpy.isEmpty());
0099 
0100     history->insert(HistoryItemPtr(new HistoryStringItem(barText)));
0101     QVERIFY(!history->topIsUserSelected());
0102     QCOMPARE(history->first()->text(), barText);
0103     QCOMPARE(history->first()->next_uuid(), fooUuid);
0104     QCOMPARE(history->first()->previous_uuid(), fooUuid);
0105     QCOMPARE(history->find(fooUuid)->next_uuid(), barUuid);
0106     QCOMPARE(history->find(fooUuid)->previous_uuid(), barUuid);
0107     QCOMPARE(topSpy.size(), 1);
0108     topSpy.clear();
0109     QVERIFY(topSpy.isEmpty());
0110 
0111     history->insert(HistoryItemPtr(new HistoryStringItem(fooBarText)));
0112     QVERIFY(!history->topIsUserSelected());
0113     QCOMPARE(history->first()->text(), fooBarText);
0114     QCOMPARE(history->first()->next_uuid(), barUuid);
0115     QCOMPARE(history->first()->previous_uuid(), fooUuid);
0116     QCOMPARE(history->find(fooUuid)->next_uuid(), foobarUuid);
0117     QCOMPARE(history->find(fooUuid)->previous_uuid(), barUuid);
0118     QCOMPARE(history->find(barUuid)->next_uuid(), fooUuid);
0119     QCOMPARE(history->find(barUuid)->previous_uuid(), foobarUuid);
0120     QCOMPARE(topSpy.size(), 1);
0121     topSpy.clear();
0122     QVERIFY(topSpy.isEmpty());
0123 
0124     // insert one again - it should be moved to top
0125     history->insert(HistoryItemPtr(new HistoryStringItem(barText)));
0126     QVERIFY(!history->topIsUserSelected());
0127     QCOMPARE(history->first()->text(), barText);
0128     QCOMPARE(history->first()->next_uuid(), foobarUuid);
0129     QCOMPARE(history->first()->previous_uuid(), fooUuid);
0130     QCOMPARE(history->find(fooUuid)->next_uuid(), barUuid);
0131     QCOMPARE(history->find(fooUuid)->previous_uuid(), foobarUuid);
0132     QCOMPARE(history->find(foobarUuid)->next_uuid(), fooUuid);
0133     QCOMPARE(history->find(foobarUuid)->previous_uuid(), barUuid);
0134     QCOMPARE(topSpy.size(), 1);
0135     topSpy.clear();
0136     QVERIFY(topSpy.isEmpty());
0137 
0138     // move one to top using the slot
0139     // as well as the top changing, topIsUserSelected will also be signalled to show that it got re-selected
0140     history->slotMoveToTop(barUuid);
0141     QVERIFY(history->topIsUserSelected());
0142     QCOMPARE(history->first()->text(), barText);
0143     QCOMPARE(history->first()->next_uuid(), foobarUuid);
0144     QCOMPARE(history->first()->previous_uuid(), fooUuid);
0145     QCOMPARE(history->find(fooUuid)->next_uuid(), barUuid);
0146     QCOMPARE(history->find(fooUuid)->previous_uuid(), foobarUuid);
0147     QCOMPARE(history->find(foobarUuid)->next_uuid(), fooUuid);
0148     QCOMPARE(history->find(foobarUuid)->previous_uuid(), barUuid);
0149     QCOMPARE(topSpy.size(), 1);
0150     topSpy.clear();
0151     QVERIFY(topSpy.isEmpty());
0152     QCOMPARE(topUserSelectedSpy.size(), 1);
0153     topUserSelectedSpy.clear();
0154     QVERIFY(topUserSelectedSpy.isEmpty());
0155 
0156     // another one should change, though
0157     history->slotMoveToTop(foobarUuid);
0158     QVERIFY(history->topIsUserSelected());
0159     QCOMPARE(history->first()->text(), fooBarText);
0160     QCOMPARE(history->first()->next_uuid(), barUuid);
0161     QCOMPARE(history->first()->previous_uuid(), fooUuid);
0162     QCOMPARE(history->find(fooUuid)->next_uuid(), foobarUuid);
0163     QCOMPARE(history->find(fooUuid)->previous_uuid(), barUuid);
0164     QCOMPARE(history->find(barUuid)->next_uuid(), fooUuid);
0165     QCOMPARE(history->find(barUuid)->previous_uuid(), foobarUuid);
0166     QCOMPARE(topSpy.size(), 1);
0167     topSpy.clear();
0168     QVERIFY(topSpy.isEmpty());
0169 
0170     // remove them again
0171     history->remove(history->find(foobarUuid));
0172     QVERIFY(!history->topIsUserSelected());
0173     QCOMPARE(history->first()->text(), barText);
0174     QCOMPARE(history->first()->next_uuid(), fooUuid);
0175     QCOMPARE(history->first()->previous_uuid(), fooUuid);
0176     QCOMPARE(history->find(fooUuid)->next_uuid(), barUuid);
0177     QCOMPARE(history->find(fooUuid)->previous_uuid(), barUuid);
0178     QCOMPARE(topSpy.size(), 1);
0179     topSpy.clear();
0180     QVERIFY(topSpy.isEmpty());
0181 
0182     history->remove(history->find(barUuid));
0183     QVERIFY(!history->topIsUserSelected());
0184     QCOMPARE(history->first()->text(), fooText);
0185     QCOMPARE(history->first()->next_uuid(), history->first()->uuid());
0186     QCOMPARE(history->first()->previous_uuid(), history->first()->uuid());
0187     QCOMPARE(topSpy.size(), 1);
0188     topSpy.clear();
0189     QVERIFY(topSpy.isEmpty());
0190 
0191     history->remove(history->find(fooUuid));
0192     QVERIFY(!history->topIsUserSelected());
0193     QVERIFY(!history->first());
0194     QVERIFY(history->empty());
0195     QCOMPARE(topSpy.size(), 1);
0196 }
0197 
0198 void HistoryTest::testClear()
0199 {
0200     std::unique_ptr<History> history(new History(nullptr));
0201     history->setMaxSize(10);
0202     QVERIFY(history->empty());
0203     QVERIFY(!history->topIsUserSelected());
0204 
0205     history->slotClear();
0206     QVERIFY(history->empty());
0207 
0208     // insert some items
0209     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("foo"))));
0210     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("bar"))));
0211     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("foobar"))));
0212     history->slotMoveToTop(QCryptographicHash::hash(QByteArrayLiteral("bar"), QCryptographicHash::Sha1));
0213     QVERIFY(!history->empty());
0214     QVERIFY(history->topIsUserSelected());
0215     QVERIFY(history->first());
0216 
0217     // and clear
0218     QSignalSpy topSpy(history.get(), &History::topChanged);
0219     QVERIFY(topSpy.isEmpty());
0220     history->slotClear();
0221     QVERIFY(history->empty());
0222     QVERIFY(!history->first());
0223     QVERIFY(!history->topIsUserSelected());
0224     QVERIFY(!topSpy.isEmpty());
0225 }
0226 
0227 void HistoryTest::testFind()
0228 {
0229     std::unique_ptr<History> history(new History(nullptr));
0230     history->setMaxSize(10);
0231     QVERIFY(history->empty());
0232     QVERIFY(!history->find(QByteArrayLiteral("whatever")));
0233     QVERIFY(!history->find(QByteArray()));
0234 
0235     // insert some items
0236     history->insert(HistoryItemPtr(new HistoryStringItem(QStringLiteral("foo"))));
0237     QVERIFY(!history->find(QByteArrayLiteral("whatever")));
0238     QVERIFY(!history->find(QByteArray()));
0239     const QByteArray fooUuid = QCryptographicHash::hash(QByteArrayLiteral("foo"), QCryptographicHash::Sha1);
0240     QCOMPARE(history->find(fooUuid)->uuid(), fooUuid);
0241 
0242     history->slotClear();
0243     QVERIFY(!history->find(fooUuid));
0244 }
0245 
0246 void HistoryTest::testCycle()
0247 {
0248     std::unique_ptr<History> history(new History(nullptr));
0249     QSignalSpy topSpy(history.get(), &History::topChanged);
0250     history->setMaxSize(10);
0251     QVERIFY(!history->nextInCycle());
0252     QVERIFY(!history->prevInCycle());
0253 
0254     const QString fooText = QStringLiteral("foo");
0255     const QString barText = QStringLiteral("bar");
0256     const QString fooBarText = QStringLiteral("foobar");
0257     const QByteArray fooUuid = QCryptographicHash::hash(fooText.toUtf8(), QCryptographicHash::Sha1);
0258     const QByteArray barUuid = QCryptographicHash::hash(barText.toUtf8(), QCryptographicHash::Sha1);
0259     const QByteArray foobarUuid = QCryptographicHash::hash(fooBarText.toUtf8(), QCryptographicHash::Sha1);
0260 
0261     history->insert(HistoryItemPtr(new HistoryStringItem(fooText)));
0262     QCOMPARE(topSpy.size(), 1);
0263     topSpy.clear();
0264     QVERIFY(!history->nextInCycle());
0265     QVERIFY(!history->prevInCycle());
0266     // cycling to next shouldn't change anything
0267     history->cycleNext();
0268     QVERIFY(topSpy.isEmpty());
0269     QVERIFY(!history->nextInCycle());
0270     QVERIFY(!history->prevInCycle());
0271     // cycling to previous shouldn't change anything
0272     history->cyclePrev();
0273     QVERIFY(topSpy.isEmpty());
0274     QVERIFY(!history->nextInCycle());
0275     QVERIFY(!history->prevInCycle());
0276 
0277     // insert more items
0278     history->insert(HistoryItemPtr(new HistoryStringItem(barText)));
0279     QCOMPARE(topSpy.size(), 1);
0280     topSpy.clear();
0281     QCOMPARE(history->nextInCycle(), history->find(fooUuid));
0282     QVERIFY(!history->prevInCycle());
0283     // cycle to next
0284     history->cycleNext();
0285     QCOMPARE(topSpy.size(), 1);
0286     topSpy.clear();
0287     QCOMPARE(history->first(), history->find(fooUuid));
0288     QVERIFY(!history->nextInCycle());
0289     QCOMPARE(history->prevInCycle(), history->find(barUuid));
0290     // there are no more next
0291     history->cycleNext();
0292     QVERIFY(topSpy.isEmpty());
0293     // cycle to prev should restore previous state
0294     history->cyclePrev();
0295     QCOMPARE(topSpy.size(), 1);
0296     topSpy.clear();
0297     QCOMPARE(history->first(), history->find(barUuid));
0298     QCOMPARE(history->nextInCycle(), history->find(fooUuid));
0299     QVERIFY(!history->prevInCycle());
0300     // there are no more prev
0301     history->cyclePrev();
0302     QVERIFY(topSpy.isEmpty());
0303 
0304     // insert a third item
0305     history->insert(HistoryItemPtr(new HistoryStringItem(fooBarText)));
0306     QCOMPARE(topSpy.size(), 1);
0307     topSpy.clear();
0308     QCOMPARE(history->nextInCycle(), history->find(barUuid));
0309     QVERIFY(!history->prevInCycle());
0310     // cycle to next
0311     history->cycleNext();
0312     QCOMPARE(topSpy.size(), 1);
0313     topSpy.clear();
0314     QCOMPARE(history->first(), history->find(barUuid));
0315     QCOMPARE(history->nextInCycle(), history->find(fooUuid));
0316     QCOMPARE(history->prevInCycle(), history->find(foobarUuid));
0317     // cycle to next (should be last)
0318     history->cycleNext();
0319     QCOMPARE(topSpy.size(), 1);
0320     topSpy.clear();
0321     QCOMPARE(history->first(), history->find(fooUuid));
0322     QVERIFY(!history->nextInCycle());
0323     QCOMPARE(history->prevInCycle(), history->find(barUuid));
0324     // there are no more next
0325     history->cycleNext();
0326     QVERIFY(topSpy.isEmpty());
0327     // and back again
0328     history->cyclePrev();
0329     QCOMPARE(topSpy.size(), 1);
0330     topSpy.clear();
0331     QCOMPARE(history->first(), history->find(barUuid));
0332     QCOMPARE(history->nextInCycle(), history->find(fooUuid));
0333     QCOMPARE(history->prevInCycle(), history->find(foobarUuid));
0334     // one more
0335     history->cyclePrev();
0336     QCOMPARE(topSpy.size(), 1);
0337     topSpy.clear();
0338     QCOMPARE(history->first(), history->find(foobarUuid));
0339     QCOMPARE(history->nextInCycle(), history->find(barUuid));
0340     QVERIFY(!history->prevInCycle());
0341     // there are no more prev
0342     history->cyclePrev();
0343     QVERIFY(topSpy.isEmpty());
0344 }
0345 
0346 QTEST_MAIN(HistoryTest)
0347 #include "historytest.moc"