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 "kitemviews/kitemset.h"
25 Q_DECLARE_METATYPE(KItemRangeList
);
28 * Converts a KItemRangeList to a KItemSet.
30 KItemSet
KItemRangeList2KItemSet(const KItemRangeList
& itemRanges
)
33 foreach (const KItemRange
& range
, itemRanges
) {
34 for (int i
= range
.index
; i
< range
.index
+ range
.count
; ++i
) {
42 * Converts a KItemRangeList to a QSet<int>.
44 QSet
<int> KItemRangeList2QSet(const KItemRangeList
& itemRanges
)
47 foreach (const KItemRange
& range
, itemRanges
) {
48 for (int i
= range
.index
; i
< range
.index
+ range
.count
; ++i
) {
56 * Converts a KItemRangeList to a QVector<int>.
58 QVector
<int> KItemRangeList2QVector(const KItemRangeList
& itemRanges
)
61 foreach (const KItemRange
& range
, itemRanges
) {
62 for (int i
= range
.index
; i
< range
.index
+ range
.count
; ++i
) {
70 * Converts a KItemSet to a QSet<int>.
72 static QSet
<int> KItemSet2QSet(const KItemSet
& itemSet
)
75 foreach (int i
, itemSet
) {
79 // Check that the conversion was successful.
80 Q_ASSERT(itemSet
.count() == result
.count());
82 foreach (int i
, itemSet
) {
83 Q_ASSERT(result
.contains(i
));
86 foreach (int i
, result
) {
87 Q_ASSERT(itemSet
.contains(i
));
95 * The main test class.
97 class KItemSetTest
: public QObject
104 void testConstruction_data();
105 void testConstruction();
106 void testIterators_data();
107 void testIterators();
108 void testFind_data();
110 void testChangingOneItem_data();
111 void testChangingOneItem();
112 void testAddSets_data();
115 void testSubtractSets_data();
116 void testSubtractSets();
118 void testSymmetricDifference_data();
119 void testSymmetricDifference();
122 QHash
<const char*, KItemRangeList
> m_testCases
;
125 void KItemSetTest::initTestCase()
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));
144 void KItemSetTest::testConstruction_data()
146 QTest::addColumn
<KItemRangeList
>("itemRanges");
148 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
149 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
152 QTest::newRow(it
.key()) << it
.value();
157 void KItemSetTest::testConstruction()
159 QFETCH(KItemRangeList
, itemRanges
);
161 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
162 QSet
<int> itemsQSet
= KItemRangeList2QSet(itemRanges
);
164 QVERIFY(itemSet
.isValid());
165 QVERIFY(itemSet
.count() == itemsQSet
.count());
166 QCOMPARE(KItemSet2QSet(itemSet
), itemsQSet
);
168 // Test copy constructor.
169 KItemSet
copy(itemSet
);
170 QCOMPARE(itemSet
, copy
);
172 QVERIFY(itemSet
!= copy
|| itemSet
.isEmpty());
176 QVERIFY(itemSet
.isEmpty());
177 QCOMPARE(itemSet
.count(), 0);
180 void KItemSetTest::testIterators_data()
182 QTest::addColumn
<KItemRangeList
>("itemRanges");
184 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
185 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
188 QTest::newRow(it
.key()) << it
.value();
194 * Verify that the iterators work exactly like their counterparts for the
195 * equivalent QVector<int>.
197 void KItemSetTest::testIterators()
199 QFETCH(KItemRangeList
, itemRanges
);
201 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
202 QVector
<int> itemsQVector
= KItemRangeList2QVector(itemRanges
);
204 QVERIFY(itemSet
.isValid());
205 QVERIFY(itemSet
.count() == itemsQVector
.count());
207 if (itemSet
.count() == 0) {
208 QVERIFY(itemSet
.isEmpty());
209 QVERIFY(itemSet
.begin() == itemSet
.end());
210 QVERIFY(itemSet
.constBegin() == itemSet
.constEnd());
212 QVERIFY(!itemSet
.isEmpty());
213 QVERIFY(itemSet
.begin() != itemSet
.end());
214 QVERIFY(itemSet
.constBegin() != itemSet
.constEnd());
216 const int min
= itemsQVector
.first();
217 const int max
= itemsQVector
.last();
219 QCOMPARE(*itemSet
.begin(), min
);
220 QCOMPARE(*itemSet
.constBegin(), min
);
221 QCOMPARE(itemSet
.first(), min
);
223 QCOMPARE(*(--itemSet
.end()), max
);
224 QCOMPARE(*(--itemSet
.constEnd()), max
);
225 QCOMPARE(itemSet
.last(), max
);
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
);
233 QCOMPARE(testQVector
, itemsQVector
);
236 for (KItemSet::const_iterator it
= itemSet
.constBegin(), end
= itemSet
.constEnd(); it
!= end
; ++it
) {
237 testQVector
.append(*it
);
239 QCOMPARE(testQVector
, itemsQVector
);
242 foreach (int i
, itemSet
) {
243 testQVector
.append(i
);
245 QCOMPARE(testQVector
, itemsQVector
);
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();
258 while (it1
!= itemSet
.end()) {
259 if (it1
!= --itemSet
.end()) {
260 QCOMPARE(*(++it1
), *(++vectorIt1
));
261 QCOMPARE(*(++constIt1
), *(++vectorConstIt1
));
263 QCOMPARE(++it1
, itemSet
.end());
264 QCOMPARE(++vectorIt1
, itemsQVector
.end());
265 QCOMPARE(++constIt1
, itemSet
.constEnd());
266 QCOMPARE(++vectorConstIt1
, itemsQVector
.constEnd());
269 QCOMPARE(*(it2
++), *(vectorIt2
++));
270 QCOMPARE(*(constIt2
++), *(vectorConstIt2
++));
273 QCOMPARE(constIt1
, constIt2
);
274 QCOMPARE(KItemSet::const_iterator(it1
), constIt1
);
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());
286 while (it1
!= itemSet
.begin()) {
287 QCOMPARE(*(--it1
), *(--vectorIt1
));
288 QCOMPARE(*(--constIt1
), *(--vectorConstIt1
));
290 if (it2
!= itemSet
.end()) {
291 QCOMPARE(*(it2
--), *(vectorIt2
--));
292 QCOMPARE(*(constIt2
--), *(vectorConstIt2
--));
294 QCOMPARE(it2
--, itemSet
.end());
295 QCOMPARE(vectorIt2
--, itemsQVector
.end());
296 QCOMPARE(constIt2
--, itemSet
.constEnd());
297 QCOMPARE(vectorConstIt2
--, itemsQVector
.constEnd());
301 QCOMPARE(constIt1
, constIt2
);
302 QCOMPARE(KItemSet::const_iterator(it1
), constIt1
);
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());
315 void KItemSetTest::testFind_data()
317 QTest::addColumn
<KItemRangeList
>("itemRanges");
319 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
320 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
323 QTest::newRow(it
.key()) << it
.value();
329 * Test all functions that find items:
330 * contais(int), find(int), constFind(int)
332 void KItemSetTest::testFind()
334 QFETCH(KItemRangeList
, itemRanges
);
336 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
337 QSet
<int> itemsQSet
= KItemRangeList2QSet(itemRanges
);
339 QVERIFY(itemSet
.isValid());
340 QVERIFY(itemSet
.count() == itemsQSet
.count());
342 // Find the minimum and maximum items.
346 if (itemSet
.count() == 0) {
347 // Use some arbitrary values for the upcoming tests.
351 min
= *itemSet
.begin();
352 max
= *(--itemSet
.end());
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
);
362 if (itemsQSet
.contains(i
)) {
363 QVERIFY(itemSet
.contains(i
));
365 QCOMPARE(*constIt
, i
);
367 QVERIFY(!itemSet
.contains(i
));
368 QCOMPARE(it
, itemSet
.end());
369 QCOMPARE(constIt
, itemSet
.constEnd());
374 void KItemSetTest::testChangingOneItem_data()
376 QTest::addColumn
<KItemRangeList
>("itemRanges");
378 QHash
<const char*, KItemRangeList
>::const_iterator it
= m_testCases
.constBegin();
379 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
382 QTest::newRow(it
.key()) << it
.value();
388 * Test all functions that change a single item:
389 * insert(int), remove(int), erase(KItemSet::iterator)
391 void KItemSetTest::testChangingOneItem()
393 QFETCH(KItemRangeList
, itemRanges
);
395 KItemSet itemSet
= KItemRangeList2KItemSet(itemRanges
);
396 QSet
<int> itemsQSet
= KItemRangeList2QSet(itemRanges
);
398 QVERIFY(itemSet
.isValid());
399 QVERIFY(itemSet
.count() == itemsQSet
.count());
401 // Find the minimum and maximum items.
405 if (itemSet
.count() == 0) {
406 // Use some arbitrary values for the upcoming tests.
410 min
= *itemSet
.begin();
411 max
= *(--itemSet
.end());
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
) {
420 KItemSet
tmp(itemSet
);
421 const KItemSet::iterator insertedIt
= tmp
.insert(i
);
422 QCOMPARE(*insertedIt
, i
);
424 QVERIFY(tmp
.isValid());
425 QVERIFY(tmp
.contains(i
));
427 QSet
<int> expectedQSet
= itemsQSet
;
428 expectedQSet
.insert(i
);
429 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
431 if (!itemSet
.contains(i
)) {
432 QVERIFY(itemSet
!= tmp
);
433 QCOMPARE(tmp
.count(), itemSet
.count() + 1);
435 QCOMPARE(itemSet
, tmp
);
438 QCOMPARE(i
, *tmp
.find(i
));
439 QCOMPARE(i
, *tmp
.constFind(i
));
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
));
446 if (!itemSet
.contains(i
)) {
447 QCOMPARE(itemSet
, tmp
);
450 expectedQSet
.remove(i
);
451 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
456 KItemSet
tmp(itemSet
);
457 const bool removed
= tmp
.remove(i
);
459 QCOMPARE(removed
, itemSet
.contains(i
));
461 QVERIFY(tmp
.isValid());
462 QVERIFY(!tmp
.contains(i
));
464 QSet
<int> expectedQSet
= itemsQSet
;
465 expectedQSet
.remove(i
);
466 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
468 if (itemSet
.contains(i
)) {
469 QVERIFY(itemSet
!= tmp
);
470 QCOMPARE(tmp
.count(), itemSet
.count() - 1);
472 QCOMPARE(itemSet
, tmp
);
475 QCOMPARE(tmp
.end(), tmp
.find(i
));
476 QCOMPARE(tmp
.constEnd(), tmp
.constFind(i
));
479 // Test erase(KItemSet::iterator).
480 if (itemSet
.contains(i
)) {
481 KItemSet
tmp(itemSet
);
482 KItemSet::iterator it
= tmp
.find(i
);
485 QVERIFY(tmp
.isValid());
486 QVERIFY(!tmp
.contains(i
));
488 QSet
<int> expectedQSet
= itemsQSet
;
489 expectedQSet
.remove(i
);
490 QCOMPARE(KItemSet2QSet(tmp
), expectedQSet
);
492 if (itemSet
.contains(i
)) {
493 QVERIFY(itemSet
!= tmp
);
494 QCOMPARE(tmp
.count(), itemSet
.count() - 1);
496 QCOMPARE(itemSet
, tmp
);
499 QCOMPARE(tmp
.end(), tmp
.find(i
));
500 QCOMPARE(tmp
.constEnd(), tmp
.constFind(i
));
502 // Check the returen value, now contained in 'it'.
504 QCOMPARE(it
, tmp
.end());
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
));
517 QVERIFY(itemSet
.isEmpty());
518 QCOMPARE(itemSet
.count(), 0);
521 void KItemSetTest::testAddSets_data()
523 QTest::addColumn
<KItemRangeList
>("itemRanges1");
524 QTest::addColumn
<KItemRangeList
>("itemRanges2");
526 QHash
<const char*, KItemRangeList
>::const_iterator it1
= m_testCases
.constBegin();
527 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
530 QHash
<const char*, KItemRangeList
>::const_iterator it2
= m_testCases
.constBegin();
533 QByteArray name
= it1
.key() + QByteArray(" + ") + it2
.key();
534 QTest::newRow(name
) << it1
.value() << it2
.value();
542 void KItemSetTest::testAddSets()
544 QFETCH(KItemRangeList
, itemRanges1
);
545 QFETCH(KItemRangeList
, itemRanges2
);
547 KItemSet itemSet1
= KItemRangeList2KItemSet(itemRanges1
);
548 QSet
<int> itemsQSet1
= KItemRangeList2QSet(itemRanges1
);
550 KItemSet itemSet2
= KItemRangeList2KItemSet(itemRanges2
);
551 QSet
<int> itemsQSet2
= KItemRangeList2QSet(itemRanges2
);
553 KItemSet sum
= itemSet1
+ itemSet2
;
554 QSet
<int> sumQSet
= itemsQSet1
+ itemsQSet2
;
556 QCOMPARE(sum
.count(), sumQSet
.count());
557 QCOMPARE(KItemSet2QSet(sum
), sumQSet
);
560 void KItemSetTest::testSymmetricDifference_data()
562 QTest::addColumn
<KItemRangeList
>("itemRanges1");
563 QTest::addColumn
<KItemRangeList
>("itemRanges2");
565 QHash
<const char*, KItemRangeList
>::const_iterator it1
= m_testCases
.constBegin();
566 const QHash
<const char*, KItemRangeList
>::const_iterator end
= m_testCases
.constEnd();
569 QHash
<const char*, KItemRangeList
>::const_iterator it2
= m_testCases
.constBegin();
572 QByteArray name
= it1
.key() + QByteArray(" ^ ") + it2
.key();
573 QTest::newRow(name
) << it1
.value() << it2
.value();
581 void KItemSetTest::testSymmetricDifference()
583 QFETCH(KItemRangeList
, itemRanges1
);
584 QFETCH(KItemRangeList
, itemRanges2
);
586 KItemSet itemSet1
= KItemRangeList2KItemSet(itemRanges1
);
587 QSet
<int> itemsQSet1
= KItemRangeList2QSet(itemRanges1
);
589 KItemSet itemSet2
= KItemRangeList2KItemSet(itemRanges2
);
590 QSet
<int> itemsQSet2
= KItemRangeList2QSet(itemRanges2
);
592 KItemSet symmetricDifference
= itemSet1
^ itemSet2
;
593 QSet
<int> symmetricDifferenceQSet
= (itemsQSet1
- itemsQSet2
) + (itemsQSet2
- itemsQSet1
);
595 QCOMPARE(symmetricDifference
.count(), symmetricDifferenceQSet
.count());
596 QCOMPARE(KItemSet2QSet(symmetricDifference
), symmetricDifferenceQSet
);
598 // Check commutativity.
599 QCOMPARE(itemSet2
^ itemSet1
, symmetricDifference
);
602 // itemSet1 ^ symmetricDifference == itemSet2,
603 // itemSet2 ^ symmetricDifference == itemSet1.
604 QCOMPARE(itemSet1
^ symmetricDifference
, itemSet2
);
605 QCOMPARE(itemSet2
^ symmetricDifference
, itemSet1
);
609 QTEST_GUILESS_MAIN(KItemSetTest
)
611 #include "kitemsettest.moc"