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