1 /***************************************************************************
2 * Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com> *
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. *
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. *
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 ***************************************************************************/
20 #include <qtest_kde.h>
22 #include "kitemviews/kitemset.h"
26 Q_DECLARE_METATYPE(KItemRangeList
);
29 * Converts a KItemRangeList to a KItemSet.
31 KItemSet
KItemRangeList2KItemSet(const KItemRangeList
& itemRanges
)
34 foreach (const KItemRange
& range
, itemRanges
) {
35 for (int i
= range
.index
; i
< range
.index
+ range
.count
; ++i
) {
43 * Converts a KItemRangeList to a QSet<int>.
45 QSet
<int> KItemRangeList2QSet(const KItemRangeList
& itemRanges
)
48 foreach (const KItemRange
& range
, itemRanges
) {
49 for (int i
= range
.index
; i
< range
.index
+ range
.count
; ++i
) {
57 * Converts a KItemRangeList to a QVector<int>.
59 QVector
<int> KItemRangeList2QVector(const KItemRangeList
& itemRanges
)
62 foreach (const KItemRange
& range
, itemRanges
) {
63 for (int i
= range
.index
; i
< range
.index
+ range
.count
; ++i
) {
71 * Converts a KItemSet to a QSet<int>.
73 static QSet
<int> KItemSet2QSet(const KItemSet
& itemSet
)
76 foreach (int i
, itemSet
) {
80 // Check that the conversion was successful.
81 Q_ASSERT(itemSet
.count() == result
.count());
83 foreach (int i
, itemSet
) {
84 Q_ASSERT(result
.contains(i
));
87 foreach (int i
, result
) {
88 Q_ASSERT(itemSet
.contains(i
));
96 * The main test class.
98 class KItemSetTest
: public QObject
105 void testConstruction_data();
106 void testConstruction();
107 void testIterators_data();
108 void testIterators();
109 void testFind_data();
111 void testChangingOneItem_data();
112 void testChangingOneItem();
113 void testAddSets_data();
116 void testSubtractSets_data();
117 void testSubtractSets();
119 void testSymmetricDifference_data();
120 void testSymmetricDifference();
123 QHash
<const char*, KItemRangeList
> m_testCases
;
126 void KItemSetTest::initTestCase()
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));
145 void KItemSetTest::testConstruction_data()
147 QTest::addColumn
<KItemRangeList
>("itemRanges");
149 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
150 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
153 QTest::newRow(it
.key()) << it
.value();
158 void KItemSetTest::testConstruction()
160 QFETCH(KItemRangeList
, itemRanges
);
162 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
163 QSet
<int> itemsQSet
= KItemRangeList2QSet(itemRanges
);
165 QVERIFY(itemSet
.isValid());
166 QVERIFY(itemSet
.count() == itemsQSet
.count());
167 QCOMPARE(KItemSet2QSet(itemSet
), itemsQSet
);
169 // Test copy constructor.
170 KItemSet
copy(itemSet
);
171 QCOMPARE(itemSet
, copy
);
173 QVERIFY(itemSet
!= copy
|| itemSet
.isEmpty());
177 QVERIFY(itemSet
.isEmpty());
178 QCOMPARE(itemSet
.count(), 0);
181 void KItemSetTest::testIterators_data()
183 QTest::addColumn
<KItemRangeList
>("itemRanges");
185 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
186 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
189 QTest::newRow(it
.key()) << it
.value();
195 * Verify that the iterators work exactly like their counterparts for the
196 * equivalent QVector<int>.
198 void KItemSetTest::testIterators()
200 QFETCH(KItemRangeList
, itemRanges
);
202 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
203 QVector
<int> itemsQVector
= KItemRangeList2QVector(itemRanges
);
205 QVERIFY(itemSet
.isValid());
206 QVERIFY(itemSet
.count() == itemsQVector
.count());
208 if (itemSet
.count() == 0) {
209 QVERIFY(itemSet
.isEmpty());
210 QVERIFY(itemSet
.begin() == itemSet
.end());
211 QVERIFY(itemSet
.constBegin() == itemSet
.constEnd());
213 QVERIFY(!itemSet
.isEmpty());
214 QVERIFY(itemSet
.begin() != itemSet
.end());
215 QVERIFY(itemSet
.constBegin() != itemSet
.constEnd());
217 const int min
= itemsQVector
.first();
218 const int max
= itemsQVector
.last();
220 QCOMPARE(*itemSet
.begin(), min
);
221 QCOMPARE(*itemSet
.constBegin(), min
);
222 QCOMPARE(itemSet
.first(), min
);
224 QCOMPARE(*(--itemSet
.end()), max
);
225 QCOMPARE(*(--itemSet
.constEnd()), max
);
226 QCOMPARE(itemSet
.last(), max
);
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
);
234 QCOMPARE(testQVector
, itemsQVector
);
237 for (KItemSet::const_iterator it
= itemSet
.constBegin(), end
= itemSet
.constEnd(); it
!= end
; ++it
) {
238 testQVector
.append(*it
);
240 QCOMPARE(testQVector
, itemsQVector
);
243 foreach (int i
, itemSet
) {
244 testQVector
.append(i
);
246 QCOMPARE(testQVector
, itemsQVector
);
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();
259 while (it1
!= itemSet
.end()) {
260 if (it1
!= --itemSet
.end()) {
261 QCOMPARE(*(++it1
), *(++vectorIt1
));
262 QCOMPARE(*(++constIt1
), *(++vectorConstIt1
));
264 QCOMPARE(++it1
, itemSet
.end());
265 QCOMPARE(++vectorIt1
, itemsQVector
.end());
266 QCOMPARE(++constIt1
, itemSet
.constEnd());
267 QCOMPARE(++vectorConstIt1
, itemsQVector
.constEnd());
270 QCOMPARE(*(it2
++), *(vectorIt2
++));
271 QCOMPARE(*(constIt2
++), *(vectorConstIt2
++));
274 QCOMPARE(constIt1
, constIt2
);
275 QCOMPARE(KItemSet::const_iterator(it1
), constIt1
);
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());
287 while (it1
!= itemSet
.begin()) {
288 QCOMPARE(*(--it1
), *(--vectorIt1
));
289 QCOMPARE(*(--constIt1
), *(--vectorConstIt1
));
291 if (it2
!= itemSet
.end()) {
292 QCOMPARE(*(it2
--), *(vectorIt2
--));
293 QCOMPARE(*(constIt2
--), *(vectorConstIt2
--));
295 QCOMPARE(it2
--, itemSet
.end());
296 QCOMPARE(vectorIt2
--, itemsQVector
.end());
297 QCOMPARE(constIt2
--, itemSet
.constEnd());
298 QCOMPARE(vectorConstIt2
--, itemsQVector
.constEnd());
302 QCOMPARE(constIt1
, constIt2
);
303 QCOMPARE(KItemSet::const_iterator(it1
), constIt1
);
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());
316 void KItemSetTest::testFind_data()
318 QTest::addColumn
<KItemRangeList
>("itemRanges");
320 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
321 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
324 QTest::newRow(it
.key()) << it
.value();
330 * Test all functions that find items:
331 * contais(int), find(int), constFind(int)
333 void KItemSetTest::testFind()
335 QFETCH(KItemRangeList
, itemRanges
);
337 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
338 QSet
<int> itemsQSet
= KItemRangeList2QSet(itemRanges
);
340 QVERIFY(itemSet
.isValid());
341 QVERIFY(itemSet
.count() == itemsQSet
.count());
343 // Find the minimum and maximum items.
347 if (itemSet
.count() == 0) {
348 // Use some arbitrary values for the upcoming tests.
352 min
= *itemSet
.begin();
353 max
= *(--itemSet
.end());
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
);
363 if (itemsQSet
.contains(i
)) {
364 QVERIFY(itemSet
.contains(i
));
366 QCOMPARE(*constIt
, i
);
368 QVERIFY(!itemSet
.contains(i
));
369 QCOMPARE(it
, itemSet
.end());
370 QCOMPARE(constIt
, itemSet
.constEnd());
375 void KItemSetTest::testChangingOneItem_data()
377 QTest::addColumn
<KItemRangeList
>("itemRanges");
379 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
380 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
383 QTest::newRow(it
.key()) << it
.value();
389 * Test all functions that change a single item:
390 * insert(int), remove(int), erase(KItemSet::iterator)
392 void KItemSetTest::testChangingOneItem()
394 QFETCH(KItemRangeList
, itemRanges
);
396 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
397 QSet
<int> itemsQSet
= KItemRangeList2QSet(itemRanges
);
399 QVERIFY(itemSet
.isValid());
400 QVERIFY(itemSet
.count() == itemsQSet
.count());
402 // Find the minimum and maximum items.
406 if (itemSet
.count() == 0) {
407 // Use some arbitrary values for the upcoming tests.
411 min
= *itemSet
.begin();
412 max
= *(--itemSet
.end());
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
) {
421 KItemSet
tmp(itemSet
);
422 const KItemSet::iterator insertedIt
= tmp
.insert(i
);
423 QCOMPARE(*insertedIt
, i
);
425 QVERIFY(tmp
.isValid());
426 QVERIFY(tmp
.contains(i
));
428 QSet
<int> expectedQSet
= itemsQSet
;
429 expectedQSet
.insert(i
);
430 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
432 if (!itemSet
.contains(i
)) {
433 QVERIFY(itemSet
!= tmp
);
434 QCOMPARE(tmp
.count(), itemSet
.count() + 1);
436 QCOMPARE(itemSet
, tmp
);
439 QCOMPARE(i
, *tmp
.find(i
));
440 QCOMPARE(i
, *tmp
.constFind(i
));
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
));
447 if (!itemSet
.contains(i
)) {
448 QCOMPARE(itemSet
, tmp
);
451 expectedQSet
.remove(i
);
452 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
457 KItemSet
tmp(itemSet
);
458 const bool removed
= tmp
.remove(i
);
460 QCOMPARE(removed
, itemSet
.contains(i
));
462 QVERIFY(tmp
.isValid());
463 QVERIFY(!tmp
.contains(i
));
465 QSet
<int> expectedQSet
= itemsQSet
;
466 expectedQSet
.remove(i
);
467 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
469 if (itemSet
.contains(i
)) {
470 QVERIFY(itemSet
!= tmp
);
471 QCOMPARE(tmp
.count(), itemSet
.count() - 1);
473 QCOMPARE(itemSet
, tmp
);
476 QCOMPARE(tmp
.end(), tmp
.find(i
));
477 QCOMPARE(tmp
.constEnd(), tmp
.constFind(i
));
480 // Test erase(KItemSet::iterator).
481 if (itemSet
.contains(i
)) {
482 KItemSet
tmp(itemSet
);
483 KItemSet::iterator it
= tmp
.find(i
);
486 QVERIFY(tmp
.isValid());
487 QVERIFY(!tmp
.contains(i
));
489 QSet
<int> expectedQSet
= itemsQSet
;
490 expectedQSet
.remove(i
);
491 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
493 if (itemSet
.contains(i
)) {
494 QVERIFY(itemSet
!= tmp
);
495 QCOMPARE(tmp
.count(), itemSet
.count() - 1);
497 QCOMPARE(itemSet
, tmp
);
500 QCOMPARE(tmp
.end(), tmp
.find(i
));
501 QCOMPARE(tmp
.constEnd(), tmp
.constFind(i
));
503 // Check the returen value, now contained in 'it'.
505 QCOMPARE(it
, tmp
.end());
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
));
518 QVERIFY(itemSet
.isEmpty());
519 QCOMPARE(itemSet
.count(), 0);
522 void KItemSetTest::testAddSets_data()
524 QTest::addColumn
<KItemRangeList
>("itemRanges1");
525 QTest::addColumn
<KItemRangeList
>("itemRanges2");
527 QHash
<const char*, KItemRangeList
>::const_iterator it1
= m_testCases
.constBegin();
528 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
531 QHash
<const char*, KItemRangeList
>::const_iterator it2
= m_testCases
.constBegin();
534 QByteArray name
= it1
.key() + QByteArray(" + ") + it2
.key();
535 QTest::newRow(name
) << it1
.value() << it2
.value();
543 void KItemSetTest::testAddSets()
545 QFETCH(KItemRangeList
, itemRanges1
);
546 QFETCH(KItemRangeList
, itemRanges2
);
548 KItemSet itemSet1
= KItemRangeList2KItemSet(itemRanges1
);
549 QSet
<int> itemsQSet1
= KItemRangeList2QSet(itemRanges1
);
551 KItemSet itemSet2
= KItemRangeList2KItemSet(itemRanges2
);
552 QSet
<int> itemsQSet2
= KItemRangeList2QSet(itemRanges2
);
554 KItemSet sum
= itemSet1
+ itemSet2
;
555 QSet
<int> sumQSet
= itemsQSet1
+ itemsQSet2
;
557 QCOMPARE(sum
.count(), sumQSet
.count());
558 QCOMPARE(KItemSet2QSet(sum
), sumQSet
);
561 void KItemSetTest::testSymmetricDifference_data()
563 QTest::addColumn
<KItemRangeList
>("itemRanges1");
564 QTest::addColumn
<KItemRangeList
>("itemRanges2");
566 QHash
<const char*, KItemRangeList
>::const_iterator it1
= m_testCases
.constBegin();
567 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
570 QHash
<const char*, KItemRangeList
>::const_iterator it2
= m_testCases
.constBegin();
573 QByteArray name
= it1
.key() + QByteArray(" ^ ") + it2
.key();
574 QTest::newRow(name
) << it1
.value() << it2
.value();
582 void KItemSetTest::testSymmetricDifference()
584 QFETCH(KItemRangeList
, itemRanges1
);
585 QFETCH(KItemRangeList
, itemRanges2
);
587 KItemSet itemSet1
= KItemRangeList2KItemSet(itemRanges1
);
588 QSet
<int> itemsQSet1
= KItemRangeList2QSet(itemRanges1
);
590 KItemSet itemSet2
= KItemRangeList2KItemSet(itemRanges2
);
591 QSet
<int> itemsQSet2
= KItemRangeList2QSet(itemRanges2
);
593 KItemSet symmetricDifference
= itemSet1
^ itemSet2
;
594 QSet
<int> symmetricDifferenceQSet
= (itemsQSet1
- itemsQSet2
) + (itemsQSet2
- itemsQSet1
);
596 QCOMPARE(symmetricDifference
.count(), symmetricDifferenceQSet
.count());
597 QCOMPARE(KItemSet2QSet(symmetricDifference
), symmetricDifferenceQSet
);
599 // Check commutativity.
600 QCOMPARE(itemSet2
^ itemSet1
, symmetricDifference
);
603 // itemSet1 ^ symmetricDifference == itemSet2,
604 // itemSet2 ^ symmetricDifference == itemSet1.
605 QCOMPARE(itemSet1
^ symmetricDifference
, itemSet2
);
606 QCOMPARE(itemSet2
^ symmetricDifference
, itemSet1
);
610 QTEST_KDEMAIN(KItemSetTest
, NoGUI
)
612 #include "kitemsettest.moc"