]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/kitemsettest.cpp
2832596ba689a6ef07b444e4a92447dd218b881d
[dolphin.git] / src / tests / kitemsettest.cpp
1 /***************************************************************************
2 * Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include <qtest_kde.h>
21
22 #include "kitemviews/kitemset.h"
23
24 #include <QVector>
25
26 Q_DECLARE_METATYPE(KItemRangeList);
27
28 /**
29 * Converts a KItemRangeList to a KItemSet.
30 */
31 KItemSet KItemRangeList2KItemSet(const KItemRangeList& itemRanges)
32 {
33 KItemSet result;
34 foreach (const KItemRange& range, itemRanges) {
35 for (int i = range.index; i < range.index + range.count; ++i) {
36 result.insert(i);
37 }
38 }
39 return result;
40 }
41
42 /**
43 * Converts a KItemRangeList to a QSet<int>.
44 */
45 QSet<int> KItemRangeList2QSet(const KItemRangeList& itemRanges)
46 {
47 QSet<int> result;
48 foreach (const KItemRange& range, itemRanges) {
49 for (int i = range.index; i < range.index + range.count; ++i) {
50 result.insert(i);
51 }
52 }
53 return result;
54 }
55
56 /**
57 * Converts a KItemRangeList to a QVector<int>.
58 */
59 QVector<int> KItemRangeList2QVector(const KItemRangeList& itemRanges)
60 {
61 QVector<int> result;
62 foreach (const KItemRange& range, itemRanges) {
63 for (int i = range.index; i < range.index + range.count; ++i) {
64 result.append(i);
65 }
66 }
67 return result;
68 }
69
70 /**
71 * Converts a KItemSet to a QSet<int>.
72 */
73 static QSet<int> KItemSet2QSet(const KItemSet& itemSet)
74 {
75 QSet<int> result;
76 foreach (int i, itemSet) {
77 result.insert(i);
78 }
79
80 // Check that the conversion was successful.
81 Q_ASSERT(itemSet.count() == result.count());
82
83 foreach (int i, itemSet) {
84 Q_ASSERT(result.contains(i));
85 }
86
87 foreach (int i, result) {
88 Q_ASSERT(itemSet.contains(i));
89 }
90
91 return result;
92 }
93
94
95 /**
96 * The main test class.
97 */
98 class KItemSetTest : public QObject
99 {
100 Q_OBJECT
101
102 private slots:
103 void initTestCase();
104
105 void testConstruction_data();
106 void testConstruction();
107 void testIterators_data();
108 void testIterators();
109 void testFind_data();
110 void testFind();
111 void testChangingOneItem_data();
112 void testChangingOneItem();
113 void testAddSets_data();
114 void testAddSets();
115 /*
116 void testSubtractSets_data();
117 void testSubtractSets();
118 */
119 void testSymmetricDifference_data();
120 void testSymmetricDifference();
121
122 private:
123 QHash<const char*, KItemRangeList> m_testCases;
124 };
125
126 void KItemSetTest::initTestCase()
127 {
128 m_testCases.insert("empty", KItemRangeList());
129 m_testCases.insert("[0]", KItemRangeList() << KItemRange(0, 1));
130 m_testCases.insert("[1]", KItemRangeList() << KItemRange(1, 1));
131 m_testCases.insert("[1, 2]", KItemRangeList() << KItemRange(1, 2));
132 m_testCases.insert("[1, 2] [5]", KItemRangeList() << KItemRange(1, 2) << KItemRange(5, 1));
133 m_testCases.insert("[1] [4, 5]", KItemRangeList() << KItemRange(1, 1) << KItemRange(4, 2));
134 m_testCases.insert("[1, 2] [4, 5]", KItemRangeList() << KItemRange(1, 2) << KItemRange(4, 2));
135 m_testCases.insert("[1, 5]", KItemRangeList() << KItemRange(1, 5));
136 m_testCases.insert("[1, 2] [4, 5] [7] [9, 10] [13] [20, 25] [30]",
137 KItemRangeList() << KItemRange(1, 2) << KItemRange(4, 2) << KItemRange(7, 1) << KItemRange(9, 2) << KItemRange(20, 6) << KItemRange(30, 1));
138 m_testCases.insert("[-10, -1]", KItemRangeList() << KItemRange(-10, 10));
139 m_testCases.insert("[-10, 0]", KItemRangeList() << KItemRange(-10, 11));
140 m_testCases.insert("[-10, 1]", KItemRangeList() << KItemRange(-10, 12));
141 m_testCases.insert("[0, 9]", KItemRangeList() << KItemRange(0, 10));
142 m_testCases.insert("[0, 19]", KItemRangeList() << KItemRange(0, 10));
143 }
144
145 void KItemSetTest::testConstruction_data()
146 {
147 QTest::addColumn<KItemRangeList>("itemRanges");
148
149 QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
150 const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
151
152 while (it != end) {
153 QTest::newRow(it.key()) << it.value();
154 ++it;
155 }
156 }
157
158 void KItemSetTest::testConstruction()
159 {
160 QFETCH(KItemRangeList, itemRanges);
161
162 KItemSet itemSet = KItemRangeList2KItemSet(itemRanges);
163 QSet<int> itemsQSet = KItemRangeList2QSet(itemRanges);
164
165 QVERIFY(itemSet.isValid());
166 QVERIFY(itemSet.count() == itemsQSet.count());
167 QCOMPARE(KItemSet2QSet(itemSet), itemsQSet);
168
169 // Test copy constructor.
170 KItemSet copy(itemSet);
171 QCOMPARE(itemSet, copy);
172 copy.clear();
173 QVERIFY(itemSet != copy || itemSet.isEmpty());
174
175 // Clear the set.
176 itemSet.clear();
177 QVERIFY(itemSet.isEmpty());
178 QCOMPARE(itemSet.count(), 0);
179 }
180
181 void KItemSetTest::testIterators_data()
182 {
183 QTest::addColumn<KItemRangeList>("itemRanges");
184
185 QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
186 const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
187
188 while (it != end) {
189 QTest::newRow(it.key()) << it.value();
190 ++it;
191 }
192 }
193
194 /**
195 * Verify that the iterators work exactly like their counterparts for the
196 * equivalent QVector<int>.
197 */
198 void KItemSetTest::testIterators()
199 {
200 QFETCH(KItemRangeList, itemRanges);
201
202 KItemSet itemSet = KItemRangeList2KItemSet(itemRanges);
203 QVector<int> itemsQVector = KItemRangeList2QVector(itemRanges);
204
205 QVERIFY(itemSet.isValid());
206 QVERIFY(itemSet.count() == itemsQVector.count());
207
208 if (itemSet.count() == 0) {
209 QVERIFY(itemSet.isEmpty());
210 QVERIFY(itemSet.begin() == itemSet.end());
211 QVERIFY(itemSet.constBegin() == itemSet.constEnd());
212 } else {
213 QVERIFY(!itemSet.isEmpty());
214 QVERIFY(itemSet.begin() != itemSet.end());
215 QVERIFY(itemSet.constBegin() != itemSet.constEnd());
216
217 const int min = itemsQVector.first();
218 const int max = itemsQVector.last();
219
220 QCOMPARE(*itemSet.begin(), min);
221 QCOMPARE(*itemSet.constBegin(), min);
222 QCOMPARE(itemSet.first(), min);
223
224 QCOMPARE(*(--itemSet.end()), max);
225 QCOMPARE(*(--itemSet.constEnd()), max);
226 QCOMPARE(itemSet.last(), max);
227 }
228
229 // Test iterating using the different iterators.
230 QVector<int> testQVector;
231 for (KItemSet::iterator it = itemSet.begin(), end = itemSet.end(); it != end; ++it) {
232 testQVector.append(*it);
233 }
234 QCOMPARE(testQVector, itemsQVector);
235
236 testQVector.clear();
237 for (KItemSet::const_iterator it = itemSet.constBegin(), end = itemSet.constEnd(); it != end; ++it) {
238 testQVector.append(*it);
239 }
240 QCOMPARE(testQVector, itemsQVector);
241
242 testQVector.clear();
243 foreach (int i, itemSet) {
244 testQVector.append(i);
245 }
246 QCOMPARE(testQVector, itemsQVector);
247
248 // Verify that both variants of the (const)iterator's operator++ and
249 // operator-- functions behave exactly like their QVector equivalents.
250 KItemSet::iterator it1 = itemSet.begin();
251 KItemSet::iterator it2 = itemSet.begin();
252 KItemSet::const_iterator constIt1 = itemSet.constBegin();
253 KItemSet::const_iterator constIt2 = itemSet.constBegin();
254 QVector<int>::iterator vectorIt1 = itemsQVector.begin();
255 QVector<int>::iterator vectorIt2 = itemsQVector.begin();
256 QVector<int>::const_iterator vectorConstIt1 = itemsQVector.constBegin();
257 QVector<int>::const_iterator vectorConstIt2 = itemsQVector.constBegin();
258
259 while (it1 != itemSet.end()) {
260 if (it1 != --itemSet.end()) {
261 QCOMPARE(*(++it1), *(++vectorIt1));
262 QCOMPARE(*(++constIt1), *(++vectorConstIt1));
263 } else {
264 QCOMPARE(++it1, itemSet.end());
265 QCOMPARE(++vectorIt1, itemsQVector.end());
266 QCOMPARE(++constIt1, itemSet.constEnd());
267 QCOMPARE(++vectorConstIt1, itemsQVector.constEnd());
268 }
269
270 QCOMPARE(*(it2++), *(vectorIt2++));
271 QCOMPARE(*(constIt2++), *(vectorConstIt2++));
272
273 QCOMPARE(it1, it2);
274 QCOMPARE(constIt1, constIt2);
275 QCOMPARE(KItemSet::const_iterator(it1), constIt1);
276 }
277
278 QCOMPARE(it1, itemSet.end());
279 QCOMPARE(it2, itemSet.end());
280 QCOMPARE(constIt1, itemSet.constEnd());
281 QCOMPARE(constIt2, itemSet.constEnd());
282 QCOMPARE(vectorIt1, itemsQVector.end());
283 QCOMPARE(vectorIt2, itemsQVector.end());
284 QCOMPARE(vectorConstIt1, itemsQVector.constEnd());
285 QCOMPARE(vectorConstIt2, itemsQVector.constEnd());
286
287 while (it1 != itemSet.begin()) {
288 QCOMPARE(*(--it1), *(--vectorIt1));
289 QCOMPARE(*(--constIt1), *(--vectorConstIt1));
290
291 if (it2 != itemSet.end()) {
292 QCOMPARE(*(it2--), *(vectorIt2--));
293 QCOMPARE(*(constIt2--), *(vectorConstIt2--));
294 } else {
295 QCOMPARE(it2--, itemSet.end());
296 QCOMPARE(vectorIt2--, itemsQVector.end());
297 QCOMPARE(constIt2--, itemSet.constEnd());
298 QCOMPARE(vectorConstIt2--, itemsQVector.constEnd());
299 }
300
301 QCOMPARE(it1, it2);
302 QCOMPARE(constIt1, constIt2);
303 QCOMPARE(KItemSet::const_iterator(it1), constIt1);
304 }
305
306 QCOMPARE(it1, itemSet.begin());
307 QCOMPARE(it2, itemSet.begin());
308 QCOMPARE(constIt1, itemSet.constBegin());
309 QCOMPARE(constIt2, itemSet.constBegin());
310 QCOMPARE(vectorIt1, itemsQVector.begin());
311 QCOMPARE(vectorIt2, itemsQVector.begin());
312 QCOMPARE(vectorConstIt1, itemsQVector.constBegin());
313 QCOMPARE(vectorConstIt2, itemsQVector.constBegin());
314 }
315
316 void KItemSetTest::testFind_data()
317 {
318 QTest::addColumn<KItemRangeList>("itemRanges");
319
320 QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
321 const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
322
323 while (it != end) {
324 QTest::newRow(it.key()) << it.value();
325 ++it;
326 }
327 }
328
329 /**
330 * Test all functions that find items:
331 * contais(int), find(int), constFind(int)
332 */
333 void KItemSetTest::testFind()
334 {
335 QFETCH(KItemRangeList, itemRanges);
336
337 KItemSet itemSet = KItemRangeList2KItemSet(itemRanges);
338 QSet<int> itemsQSet = KItemRangeList2QSet(itemRanges);
339
340 QVERIFY(itemSet.isValid());
341 QVERIFY(itemSet.count() == itemsQSet.count());
342
343 // Find the minimum and maximum items.
344 int min;
345 int max;
346
347 if (itemSet.count() == 0) {
348 // Use some arbitrary values for the upcoming tests.
349 min = 0;
350 max = 5;
351 } else {
352 min = *itemSet.begin();
353 max = *(--itemSet.end());
354 }
355
356 // Test contains(int), find(int), and constFind(int)
357 // for items between min - 2 and max + 2.
358 for (int i = min - 2; i <= max + 2; ++i) {
359 const KItemSet::iterator it = itemSet.find(i);
360 const KItemSet::const_iterator constIt = itemSet.constFind(i);
361 QCOMPARE(KItemSet::const_iterator(it), constIt);
362
363 if (itemsQSet.contains(i)) {
364 QVERIFY(itemSet.contains(i));
365 QCOMPARE(*it, i);
366 QCOMPARE(*constIt, i);
367 } else {
368 QVERIFY(!itemSet.contains(i));
369 QCOMPARE(it, itemSet.end());
370 QCOMPARE(constIt, itemSet.constEnd());
371 }
372 }
373 }
374
375 void KItemSetTest::testChangingOneItem_data()
376 {
377 QTest::addColumn<KItemRangeList>("itemRanges");
378
379 QHash<const char*, KItemRangeList>::const_iterator it = m_testCases.constBegin();
380 const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
381
382 while (it != end) {
383 QTest::newRow(it.key()) << it.value();
384 ++it;
385 }
386 }
387
388 /**
389 * Test all functions that change a single item:
390 * insert(int), remove(int), erase(KItemSet::iterator)
391 */
392 void KItemSetTest::testChangingOneItem()
393 {
394 QFETCH(KItemRangeList, itemRanges);
395
396 KItemSet itemSet = KItemRangeList2KItemSet(itemRanges);
397 QSet<int> itemsQSet = KItemRangeList2QSet(itemRanges);
398
399 QVERIFY(itemSet.isValid());
400 QVERIFY(itemSet.count() == itemsQSet.count());
401
402 // Find the minimum and maximum items.
403 int min;
404 int max;
405
406 if (itemSet.count() == 0) {
407 // Use some arbitrary values for the upcoming tests.
408 min = 0;
409 max = 5;
410 } else {
411 min = *itemSet.begin();
412 max = *(--itemSet.end());
413 }
414
415 // Test insert(int), remove(int), and erase(KItemSet::iterator)
416 // for items between min - 2 and max + 2.
417 for (int i = min - 2; i <= max + 2; ++i) {
418
419 // Test insert(int).
420 {
421 KItemSet tmp(itemSet);
422 const KItemSet::iterator insertedIt = tmp.insert(i);
423 QCOMPARE(*insertedIt, i);
424
425 QVERIFY(tmp.isValid());
426 QVERIFY(tmp.contains(i));
427
428 QSet<int> expectedQSet = itemsQSet;
429 expectedQSet.insert(i);
430 QCOMPARE(KItemSet2QSet(tmp), expectedQSet);
431
432 if (!itemSet.contains(i)) {
433 QVERIFY(itemSet != tmp);
434 QCOMPARE(tmp.count(), itemSet.count() + 1);
435 } else {
436 QCOMPARE(itemSet, tmp);
437 }
438
439 QCOMPARE(i, *tmp.find(i));
440 QCOMPARE(i, *tmp.constFind(i));
441
442 // Erase the new item and check that we get the old KItemSet back.
443 tmp.erase(tmp.find(i));
444 QVERIFY(tmp.isValid());
445 QVERIFY(!tmp.contains(i));
446
447 if (!itemSet.contains(i)) {
448 QCOMPARE(itemSet, tmp);
449 }
450
451 expectedQSet.remove(i);
452 QCOMPARE(KItemSet2QSet(tmp), expectedQSet);
453 }
454
455 // Test remove(int).
456 {
457 KItemSet tmp(itemSet);
458 const bool removed = tmp.remove(i);
459
460 QCOMPARE(removed, itemSet.contains(i));
461
462 QVERIFY(tmp.isValid());
463 QVERIFY(!tmp.contains(i));
464
465 QSet<int> expectedQSet = itemsQSet;
466 expectedQSet.remove(i);
467 QCOMPARE(KItemSet2QSet(tmp), expectedQSet);
468
469 if (itemSet.contains(i)) {
470 QVERIFY(itemSet != tmp);
471 QCOMPARE(tmp.count(), itemSet.count() - 1);
472 } else {
473 QCOMPARE(itemSet, tmp);
474 }
475
476 QCOMPARE(tmp.end(), tmp.find(i));
477 QCOMPARE(tmp.constEnd(), tmp.constFind(i));
478 }
479
480 // Test erase(KItemSet::iterator).
481 if (itemSet.contains(i)) {
482 KItemSet tmp(itemSet);
483 KItemSet::iterator it = tmp.find(i);
484 it = tmp.erase(it);
485
486 QVERIFY(tmp.isValid());
487 QVERIFY(!tmp.contains(i));
488
489 QSet<int> expectedQSet = itemsQSet;
490 expectedQSet.remove(i);
491 QCOMPARE(KItemSet2QSet(tmp), expectedQSet);
492
493 if (itemSet.contains(i)) {
494 QVERIFY(itemSet != tmp);
495 QCOMPARE(tmp.count(), itemSet.count() - 1);
496 } else {
497 QCOMPARE(itemSet, tmp);
498 }
499
500 QCOMPARE(tmp.end(), tmp.find(i));
501 QCOMPARE(tmp.constEnd(), tmp.constFind(i));
502
503 // Check the returen value, now contained in 'it'.
504 if (i == max) {
505 QCOMPARE(it, tmp.end());
506 } else {
507 // it now points to the next item.
508 QVERIFY(tmp.contains(*it));
509 for (int j = i; j < *it; ++j) {
510 QVERIFY(!tmp.contains(j));
511 }
512 }
513 }
514 }
515
516 // Clear the set.
517 itemSet.clear();
518 QVERIFY(itemSet.isEmpty());
519 QCOMPARE(itemSet.count(), 0);
520 }
521
522 void KItemSetTest::testAddSets_data()
523 {
524 QTest::addColumn<KItemRangeList>("itemRanges1");
525 QTest::addColumn<KItemRangeList>("itemRanges2");
526
527 QHash<const char*, KItemRangeList>::const_iterator it1 = m_testCases.constBegin();
528 const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
529
530 while (it1 != end) {
531 QHash<const char*, KItemRangeList>::const_iterator it2 = m_testCases.constBegin();
532
533 while (it2 != end) {
534 QByteArray name = it1.key() + QByteArray(" + ") + it2.key();
535 QTest::newRow(name) << it1.value() << it2.value();
536 ++it2;
537 }
538
539 ++it1;
540 }
541 }
542
543 void KItemSetTest::testAddSets()
544 {
545 QFETCH(KItemRangeList, itemRanges1);
546 QFETCH(KItemRangeList, itemRanges2);
547
548 KItemSet itemSet1 = KItemRangeList2KItemSet(itemRanges1);
549 QSet<int> itemsQSet1 = KItemRangeList2QSet(itemRanges1);
550
551 KItemSet itemSet2 = KItemRangeList2KItemSet(itemRanges2);
552 QSet<int> itemsQSet2 = KItemRangeList2QSet(itemRanges2);
553
554 KItemSet sum = itemSet1 + itemSet2;
555 QSet<int> sumQSet = itemsQSet1 + itemsQSet2;
556
557 QCOMPARE(sum.count(), sumQSet.count());
558 QCOMPARE(KItemSet2QSet(sum), sumQSet);
559 }
560
561 void KItemSetTest::testSymmetricDifference_data()
562 {
563 QTest::addColumn<KItemRangeList>("itemRanges1");
564 QTest::addColumn<KItemRangeList>("itemRanges2");
565
566 QHash<const char*, KItemRangeList>::const_iterator it1 = m_testCases.constBegin();
567 const QHash<const char*, KItemRangeList>::const_iterator end = m_testCases.constEnd();
568
569 while (it1 != end) {
570 QHash<const char*, KItemRangeList>::const_iterator it2 = m_testCases.constBegin();
571
572 while (it2 != end) {
573 QByteArray name = it1.key() + QByteArray(" ^ ") + it2.key();
574 QTest::newRow(name) << it1.value() << it2.value();
575 ++it2;
576 }
577
578 ++it1;
579 }
580 }
581
582 void KItemSetTest::testSymmetricDifference()
583 {
584 QFETCH(KItemRangeList, itemRanges1);
585 QFETCH(KItemRangeList, itemRanges2);
586
587 KItemSet itemSet1 = KItemRangeList2KItemSet(itemRanges1);
588 QSet<int> itemsQSet1 = KItemRangeList2QSet(itemRanges1);
589
590 KItemSet itemSet2 = KItemRangeList2KItemSet(itemRanges2);
591 QSet<int> itemsQSet2 = KItemRangeList2QSet(itemRanges2);
592
593 KItemSet symmetricDifference = itemSet1 ^ itemSet2;
594 QSet<int> symmetricDifferenceQSet = (itemsQSet1 - itemsQSet2) + (itemsQSet2 - itemsQSet1);
595
596 QCOMPARE(symmetricDifference.count(), symmetricDifferenceQSet.count());
597 QCOMPARE(KItemSet2QSet(symmetricDifference), symmetricDifferenceQSet);
598
599 // Check commutativity.
600 QCOMPARE(itemSet2 ^ itemSet1, symmetricDifference);
601
602 // Some more checks:
603 // itemSet1 ^ symmetricDifference == itemSet2,
604 // itemSet2 ^ symmetricDifference == itemSet1.
605 QCOMPARE(itemSet1 ^ symmetricDifference, itemSet2);
606 QCOMPARE(itemSet2 ^ symmetricDifference, itemSet1);
607 }
608
609
610 QTEST_KDEMAIN(KItemSetTest, NoGUI)
611
612 #include "kitemsettest.moc"