1 /*
2     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "../historymodel.h"
8 #include "../historyimageitem.h"
9 #include "../historystringitem.h"
10 #include "../historyurlitem.h"
11 
12 #include <QAbstractItemModelTester>
13 #include <QtTest>
14 
15 class HistoryModelTest : public QObject
16 {
17     Q_OBJECT
18 private Q_SLOTS:
19     void testSetMaxSize();
20     void testInsertRemove();
21     void testClear();
22     void testIndexOf();
23     void testType_data();
24     void testType();
25 };
26 
testSetMaxSize()27 void HistoryModelTest::testSetMaxSize()
28 {
29     QScopedPointer<HistoryModel> history(new HistoryModel(nullptr));
30     QScopedPointer<QAbstractItemModelTester> modelTest(new QAbstractItemModelTester(history.data()));
31 
32     QCOMPARE(history->rowCount(), 0);
33     QCOMPARE(history->maxSize(), 0);
34 
35     // insert an item - should still be empty
36     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foo"))));
37     QCOMPARE(history->rowCount(), 0);
38 
39     // now it should insert again
40     history->setMaxSize(1);
41     QCOMPARE(history->maxSize(), 1);
42     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foo"))));
43     QCOMPARE(history->rowCount(), 1);
44 
45     // insert another item, foo should get removed
46     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("bar"))));
47     QCOMPARE(history->rowCount(), 1);
48     QCOMPARE(history->data(history->index(0, 0)).toString(), QLatin1String("bar"));
49 
50     // I don't trust the model, add more items
51     history->setMaxSize(10);
52     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foo"))));
53     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foobar"))));
54     QCOMPARE(history->rowCount(), 3);
55     QCOMPARE(history->data(history->index(0, 0)).toString(), QLatin1String("foobar"));
56     QCOMPARE(history->data(history->index(1, 0)).toString(), QLatin1String("foo"));
57     QCOMPARE(history->data(history->index(2, 0)).toString(), QLatin1String("bar"));
58 
59     // setting to 0 should clear again
60     history->setMaxSize(0);
61     QCOMPARE(history->maxSize(), 0);
62     QCOMPARE(history->rowCount(), 0);
63 }
64 
testInsertRemove()65 void HistoryModelTest::testInsertRemove()
66 {
67     QScopedPointer<HistoryModel> history(new HistoryModel(nullptr));
68     QScopedPointer<QAbstractItemModelTester> modelTest(new QAbstractItemModelTester(history.data()));
69     history->setMaxSize(10);
70     QCOMPARE(history->rowCount(), 0);
71 
72     const QString fooText = QStringLiteral("foo");
73     const QString barText = QStringLiteral("bar");
74     const QString fooBarText = QStringLiteral("foobar");
75     const QByteArray fooUuid = QCryptographicHash::hash(fooText.toUtf8(), QCryptographicHash::Sha1);
76     const QByteArray barUuid = QCryptographicHash::hash(barText.toUtf8(), QCryptographicHash::Sha1);
77     const QByteArray foobarUuid = QCryptographicHash::hash(fooBarText.toUtf8(), QCryptographicHash::Sha1);
78 
79     // let's insert a few items
80     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(fooText)));
81     QModelIndex index = history->index(0, 0);
82     QCOMPARE(index.data().toString(), fooText);
83     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), index.data(Qt::UserRole + 1).toByteArray());
84     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), index.data(Qt::UserRole + 1).toByteArray());
85 
86     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(barText)));
87     QCOMPARE(index.data().toString(), barText);
88     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), fooUuid);
89     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), fooUuid);
90     index = history->indexOf(fooUuid);
91     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), barUuid);
92     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), barUuid);
93 
94     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(fooBarText)));
95     QCOMPARE(history->data(history->index(0, 0)).toString(), fooBarText);
96     index = history->index(0, 0);
97     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), barUuid);
98     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), fooUuid);
99     index = history->indexOf(fooUuid);
100     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), foobarUuid);
101     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), barUuid);
102     index = history->indexOf(barUuid);
103     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), fooUuid);
104     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), foobarUuid);
105 
106     // insert one again - it should be moved to top
107     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(barText)));
108     QCOMPARE(history->data(history->index(0, 0)).toString(), barText);
109     index = history->index(0, 0);
110     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), foobarUuid);
111     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), fooUuid);
112     index = history->indexOf(fooUuid);
113     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), barUuid);
114     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), foobarUuid);
115     index = history->indexOf(foobarUuid);
116     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), fooUuid);
117     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), barUuid);
118 
119     // move one to top using the slot
120     // already on top, shouldn't change anything
121     history->moveToTop(barUuid);
122     QCOMPARE(history->data(history->index(0, 0)).toString(), barText);
123     index = history->index(0, 0);
124     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), foobarUuid);
125     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), fooUuid);
126     index = history->indexOf(fooUuid);
127     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), barUuid);
128     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), foobarUuid);
129     index = history->indexOf(foobarUuid);
130     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), fooUuid);
131     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), barUuid);
132 
133     // another one should change, though
134     history->moveToTop(foobarUuid);
135     QCOMPARE(history->data(history->index(0, 0)).toString(), fooBarText);
136     index = history->index(0, 0);
137     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), barUuid);
138     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), fooUuid);
139     index = history->indexOf(fooUuid);
140     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), foobarUuid);
141     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), barUuid);
142     index = history->indexOf(barUuid);
143     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), fooUuid);
144     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), foobarUuid);
145 
146     // remove them again
147     QVERIFY(history->remove(foobarUuid));
148     QCOMPARE(history->data(history->index(0, 0)).toString(), barText);
149     index = history->index(0, 0);
150     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), fooUuid);
151     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), fooUuid);
152     index = history->indexOf(fooUuid);
153     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), barUuid);
154     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), barUuid);
155 
156     QVERIFY(history->remove(barUuid));
157     QCOMPARE(history->data(history->index(0, 0)).toString(), fooText);
158     index = history->index(0, 0);
159     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->next_uuid(), index.data(Qt::UserRole + 1).toByteArray());
160     QCOMPARE(index.data(Qt::UserRole).value<HistoryItemConstPtr>()->previous_uuid(), index.data(Qt::UserRole + 1).toByteArray());
161 
162     QVERIFY(history->remove(fooUuid));
163     QCOMPARE(history->rowCount(), 0);
164 }
165 
testClear()166 void HistoryModelTest::testClear()
167 {
168     QScopedPointer<HistoryModel> history(new HistoryModel(nullptr));
169     QScopedPointer<QAbstractItemModelTester> modelTest(new QAbstractItemModelTester(history.data()));
170     history->setMaxSize(10);
171     QCOMPARE(history->rowCount(), 0);
172 
173     history->clear();
174     QCOMPARE(history->rowCount(), 0);
175 
176     // insert some items
177     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foo"))));
178     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("bar"))));
179     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foobar"))));
180     history->moveToTop(QCryptographicHash::hash(QByteArrayLiteral("bar"), QCryptographicHash::Sha1));
181     QCOMPARE(history->rowCount(), 3);
182 
183     // and clear
184     history->clear();
185     QCOMPARE(history->rowCount(), 0);
186 }
187 
testIndexOf()188 void HistoryModelTest::testIndexOf()
189 {
190     QScopedPointer<HistoryModel> history(new HistoryModel(nullptr));
191     QScopedPointer<QAbstractItemModelTester> modelTest(new QAbstractItemModelTester(history.data()));
192     history->setMaxSize(10);
193     QCOMPARE(history->rowCount(), 0);
194     QVERIFY(!history->indexOf(QByteArrayLiteral("whatever")).isValid());
195     QVERIFY(!history->indexOf(QByteArray()).isValid());
196 
197     // insert some items
198     history->insert(QSharedPointer<HistoryItem>(new HistoryStringItem(QStringLiteral("foo"))));
199     QVERIFY(!history->indexOf(QByteArrayLiteral("whatever")).isValid());
200     QVERIFY(!history->indexOf(QByteArray()).isValid());
201     const QByteArray fooUuid = QCryptographicHash::hash(QByteArrayLiteral("foo"), QCryptographicHash::Sha1);
202     QVERIFY(history->indexOf(fooUuid).isValid());
203     QCOMPARE(history->indexOf(fooUuid).data(Qt::UserRole + 1).toByteArray(), fooUuid);
204 
205     history->clear();
206     QVERIFY(!history->indexOf(fooUuid).isValid());
207 }
208 
testType_data()209 void HistoryModelTest::testType_data()
210 {
211     QTest::addColumn<HistoryItem *>("item");
212     QTest::addColumn<HistoryItemType>("expectedType");
213 
214     HistoryItem *item = new HistoryStringItem(QStringLiteral("foo"));
215     QTest::newRow("text") << item << HistoryItemType::Text;
216     item = new HistoryImageItem(QPixmap());
217     QTest::newRow("image") << item << HistoryItemType::Image;
218     item = new HistoryURLItem(QList<QUrl>(), KUrlMimeData::MetaDataMap(), false);
219     QTest::newRow("url") << item << HistoryItemType::Url;
220 }
221 
testType()222 void HistoryModelTest::testType()
223 {
224     QScopedPointer<HistoryModel> history(new HistoryModel(nullptr));
225     QScopedPointer<QAbstractItemModelTester> modelTest(new QAbstractItemModelTester(history.data()));
226     history->setMaxSize(10);
227     QCOMPARE(history->rowCount(), 0);
228 
229     QFETCH(HistoryItem *, item);
230     QFETCH(HistoryItemType, expectedType);
231     history->insert(QSharedPointer<HistoryItem>(item));
232     QCOMPARE(history->index(0).data(Qt::UserRole + 2).value<HistoryItemType>(), expectedType);
233 }
234 
235 QTEST_MAIN(HistoryModelTest)
236 #include "historymodeltest.moc"
237