]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/kfileitemmodelbenchmark.cpp
Build with QT_NO_KEYWORDS
[dolphin.git] / src / tests / kfileitemmodelbenchmark.cpp
1 /*
2 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
3 * SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include <QTest>
9 #include <QSignalSpy>
10
11 #include <random>
12
13 #include "kitemviews/kfileitemmodel.h"
14 #include "kitemviews/private/kfileitemmodelsortalgorithm.h"
15
16 void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg)
17 {
18 Q_UNUSED(context)
19
20 switch (type) {
21 case QtDebugMsg:
22 break;
23 case QtWarningMsg:
24 break;
25 case QtCriticalMsg:
26 fprintf(stderr, "Critical: %s\n", msg.toLocal8Bit().data());
27 break;
28 case QtFatalMsg:
29 fprintf(stderr, "Fatal: %s\n", msg.toLocal8Bit().data());
30 abort();
31 default:
32 break;
33 }
34 }
35
36 Q_DECLARE_METATYPE(KFileItemList)
37 Q_DECLARE_METATYPE(KItemRangeList)
38
39 class KFileItemModelBenchmark : public QObject
40 {
41 Q_OBJECT
42
43 public:
44 KFileItemModelBenchmark();
45
46 private Q_SLOTS:
47 void insertAndRemoveManyItems_data();
48 void insertAndRemoveManyItems();
49
50 private:
51 static KFileItemList createFileItemList(const QStringList& fileNames, const QString& urlPrefix = QLatin1String("file:///"));
52 };
53
54 KFileItemModelBenchmark::KFileItemModelBenchmark()
55 {
56 }
57
58 void KFileItemModelBenchmark::insertAndRemoveManyItems_data()
59 {
60 QTest::addColumn<KFileItemList>("initialItems");
61 QTest::addColumn<KFileItemList>("newItems");
62 QTest::addColumn<KFileItemList>("removedItems");
63 QTest::addColumn<KFileItemList>("expectedFinalItems");
64 QTest::addColumn<KItemRangeList>("expectedItemsInserted");
65 QTest::addColumn<KItemRangeList>("expectedItemsRemoved");
66
67 QList<int> sizes;
68 sizes << 100000;
69
70 for (int n : qAsConst(sizes)) {
71 QStringList allStrings;
72 for (int i = 0; i < n; ++i) {
73 allStrings << QString::number(i);
74 }
75
76 // We want to keep the sorting overhead in the benchmark low.
77 // Therefore, we do not use natural sorting. However, this
78 // means that our list is currently not sorted.
79 allStrings.sort();
80
81 KFileItemList all = createFileItemList(allStrings);
82
83 KFileItemList firstHalf, secondHalf, even, odd;
84 for (int i = 0; i < n; ++i) {
85 if (i < n / 2) {
86 firstHalf << all.at(i);
87 } else {
88 secondHalf << all.at(i);
89 }
90
91 if (i % 2 == 0) {
92 even << all.at(i);
93 } else {
94 odd << all.at(i);
95 }
96 }
97
98 KItemRangeList itemRangeListFirstHalf;
99 itemRangeListFirstHalf << KItemRange(0, firstHalf.count());
100
101 KItemRangeList itemRangeListSecondHalf;
102 itemRangeListSecondHalf << KItemRange(firstHalf.count(), secondHalf.count());
103
104 KItemRangeList itemRangeListOddInserted, itemRangeListOddRemoved;
105 for (int i = 0; i < odd.count(); ++i) {
106 // Note that the index in the KItemRange is the index of
107 // the model *before* the items have been inserted.
108 itemRangeListOddInserted << KItemRange(i + 1, 1);
109 itemRangeListOddRemoved << KItemRange(2 * i + 1, 1);
110 }
111
112 const int bufferSize = 128;
113 char buffer[bufferSize];
114
115 snprintf(buffer, bufferSize, "all--n=%i", n);
116 QTest::newRow(buffer) << all << KFileItemList() << KFileItemList() << all << KItemRangeList() << KItemRangeList();
117
118 snprintf(buffer, bufferSize, "1st half + 2nd half--n=%i", n);
119 QTest::newRow(buffer) << firstHalf << secondHalf << KFileItemList() << all << itemRangeListSecondHalf << KItemRangeList();
120
121 snprintf(buffer, bufferSize, "2nd half + 1st half--n=%i", n);
122 QTest::newRow(buffer) << secondHalf << firstHalf << KFileItemList() << all << itemRangeListFirstHalf << KItemRangeList();
123
124 snprintf(buffer, bufferSize, "even + odd--n=%i", n);
125 QTest::newRow(buffer) << even << odd << KFileItemList() << all << itemRangeListOddInserted << KItemRangeList();
126
127 snprintf(buffer, bufferSize, "all - 2nd half--n=%i", n);
128 QTest::newRow(buffer) << all << KFileItemList() << secondHalf << firstHalf << KItemRangeList() << itemRangeListSecondHalf;
129
130 snprintf(buffer, bufferSize, "all - 1st half--n=%i", n);
131 QTest::newRow(buffer) << all << KFileItemList() << firstHalf << secondHalf << KItemRangeList() << itemRangeListFirstHalf;
132
133 snprintf(buffer, bufferSize, "all - odd--n=%i", n);
134 QTest::newRow(buffer) << all << KFileItemList() << odd << even << KItemRangeList() << itemRangeListOddRemoved;
135 }
136 }
137
138 void KFileItemModelBenchmark::insertAndRemoveManyItems()
139 {
140 QFETCH(KFileItemList, initialItems);
141 QFETCH(KFileItemList, newItems);
142 QFETCH(KFileItemList, removedItems);
143 QFETCH(KFileItemList, expectedFinalItems);
144 QFETCH(KItemRangeList, expectedItemsInserted);
145 QFETCH(KItemRangeList, expectedItemsRemoved);
146
147 KFileItemModel model;
148
149 // Avoid overhead caused by natural sorting
150 // and determining the isDir/isLink roles.
151 model.m_naturalSorting = false;
152 model.setRoles({"text"});
153
154 QSignalSpy spyItemsInserted(&model, &KFileItemModel::itemsInserted);
155 QSignalSpy spyItemsRemoved(&model, &KFileItemModel::itemsRemoved);
156
157 QBENCHMARK {
158 model.slotClear();
159 model.slotItemsAdded(model.directory(), initialItems);
160 model.slotCompleted();
161 QCOMPARE(model.count(), initialItems.count());
162
163 if (!newItems.isEmpty()) {
164 model.slotItemsAdded(model.directory(), newItems);
165 model.slotCompleted();
166 }
167 QCOMPARE(model.count(), initialItems.count() + newItems.count());
168
169 if (!removedItems.isEmpty()) {
170 model.slotItemsDeleted(removedItems);
171 }
172 QCOMPARE(model.count(), initialItems.count() + newItems.count() - removedItems.count());
173 }
174
175 QVERIFY(model.isConsistent());
176
177 for (int i = 0; i < model.count(); ++i) {
178 QCOMPARE(model.fileItem(i), expectedFinalItems.at(i));
179 }
180
181 if (!expectedItemsInserted.empty()) {
182 QVERIFY(!spyItemsInserted.empty());
183 const KItemRangeList actualItemsInserted = spyItemsInserted.last().first().value<KItemRangeList>();
184 QCOMPARE(actualItemsInserted, expectedItemsInserted);
185 }
186
187 if (!expectedItemsRemoved.empty()) {
188 QVERIFY(!spyItemsRemoved.empty());
189 const KItemRangeList actualItemsRemoved = spyItemsRemoved.last().first().value<KItemRangeList>();
190 QCOMPARE(actualItemsRemoved, expectedItemsRemoved);
191 }
192 }
193
194 KFileItemList KFileItemModelBenchmark::createFileItemList(const QStringList& fileNames, const QString& prefix)
195 {
196 // Suppress 'file does not exist anymore' messages from KFileItemPrivate::init().
197 qInstallMessageHandler(myMessageOutput);
198
199 KFileItemList result;
200 for (const QString& name : fileNames) {
201 const KFileItem item(QUrl::fromLocalFile(prefix + name), QString(), KFileItem::Unknown);
202 result << item;
203 }
204 return result;
205 }
206
207 QTEST_MAIN(KFileItemModelBenchmark)
208
209 #include "kfileitemmodelbenchmark.moc"