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