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