Remove Q_ASSERT from algorithms autotest
[qt:ritts-qtbase.git] / tests / auto / qalgorithms / tst_qalgorithms.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #include <iostream>
46 #include <iomanip>
47 #include <sstream>
48 #include <algorithm>
49 #include <qalgorithms.h>
50 #include "q3tl.h"
51 #include <QStringList>
52 #include <QString>
53 #include <QVector>
54
55 #define Q_TEST_PERFORMANCE 0
56
57 using namespace std;
58
59 //TESTED_FILES=
60
61 class tst_QAlgorithms : public QObject
62 {
63 Q_OBJECT
64
65 public:
66     tst_QAlgorithms();
67     ~tst_QAlgorithms();
68
69 public slots:
70     void init();
71     void cleanup();
72
73 private slots:
74     void qBubbleSort();
75     void qHeapSort();
76     void test_qLowerBound_data();
77     void test_qLowerBound();
78     void test_qUpperBound_data();
79     void test_qUpperBound();
80     void test_qBinaryFind_data();
81     void test_qBinaryFind();
82     void qBinaryFindOneEntry();
83     void swap();
84     void swap2();
85     void sortEmptyList();
86     void sortedList();
87     void sortAPItest();
88     void stableSortTest();
89     void stableSortCorrectnessTest_data();
90     void stableSortCorrectnessTest();
91     void convenienceAPI();
92     void qCountIterators() const;
93     void qCountContainer() const;
94     void binaryFindOnLargeContainer() const;
95
96 #if Q_TEST_PERFORMANCE
97 private:
98     void performance();
99 #endif
100 };
101
102 tst_QAlgorithms::tst_QAlgorithms()
103
104 {
105 }
106
107 tst_QAlgorithms::~tst_QAlgorithms()
108 {
109
110 }
111
112 void tst_QAlgorithms::init()
113 {
114 }
115
116 void tst_QAlgorithms::cleanup()
117 {
118 }
119
120
121 class TestInt
122 {
123 public:
124     TestInt(int number)  :m_number(number) {} ;
125     TestInt() : m_number(0) {};
126     bool operator<(const TestInt &other) const { ++TestInt::lessThanRefCount; return (m_number < other.m_number); }
127     int m_number;
128 static long int lessThanRefCount;
129 };
130
131 long int TestInt::lessThanRefCount;
132
133
134 QStringList dataSetTypes = QStringList() << "Random" << "Ascending"
135                 << "Descending" << "Equal" << "Duplicates" << "Almost Sorted"  ;
136
137 template <typename DataType>
138 QVector<DataType> generateData(QString dataSetType, const int length)
139 {
140     QVector<DataType> container;
141     if (dataSetType == "Random") {
142         for(int i=0; i < length; ++i)
143             container.append(rand());
144     }
145     else if (dataSetType == "Ascending") {
146         for (int i=0; i < length; ++i)
147             container.append(i);
148     }
149     else if (dataSetType == "Descending") {
150         for (int i=0; i < length; ++i)
151             container.append(length - i);
152     }
153     else if (dataSetType == "Equal") {
154         for (int i=0; i < length; ++i)
155             container.append(43);
156     }
157     else if (dataSetType == "Duplicates") {
158         for (int i=0; i < length; ++i)
159             container.append(i % 10);
160     }
161     else if (dataSetType == "Almost Sorted") {
162         for (int i=0; i < length; ++i)
163             container.append(i);
164         for(int i = 0; i<= length / 10; ++i) {
165             const int iswap = i * 9;
166             DataType tmp = container.at(iswap);
167             container[iswap] = container.at(iswap + 1);
168             container[iswap + 1] = tmp;
169         }
170     }
171     return container;
172 }
173
174 struct ResultSet
175 {
176     int numSorts;
177     long int lessThanRefCount;
178 };
179
180
181 template <typename ContainerType, typename Algorithm>
182 ResultSet testRun(ContainerType &container, Algorithm &algorithm, int millisecs)
183 {
184     TestInt::lessThanRefCount = 0;
185     int count = 0;
186     QTime t;
187     t.start();
188     while(t.elapsed() < millisecs) {
189         ++count;
190         algorithm(container);
191     }
192     ResultSet result;
193     result.numSorts = count;
194     result.lessThanRefCount = TestInt::lessThanRefCount;
195     return result;
196 }
197
198 template <typename ContainerType, typename LessThan>
199 bool isSorted(ContainerType &container, LessThan lessThan)
200 {
201     for (int i=0; i < container.count() - 1; ++i)
202         if (lessThan(container.at(i+1), container.at(i))) {
203             return false;
204         }
205     return true;
206 }
207
208 template <typename ContainerType>
209 bool isSorted(ContainerType &container)
210 {
211     return isSorted(container, qLess<Q_TYPENAME ContainerType::value_type>());
212 }
213
214
215 #if Q_TEST_PERFORMANCE
216 void printHeader(QStringList &headers)
217 {
218     cout << setw(10) << setiosflags(ios_base::left) << " ";
219     for (int h = 0; h < headers.count(); ++h) {
220         cout << setw(20) << setiosflags(ios_base::left) << headers.at(h).toLatin1().constData();
221     }
222     cout << endl;
223 }
224
225 template <typename ContainerType>
226 void print(ContainerType testContainer)
227 {
228     typedef typename ContainerType::value_type T;
229
230     foreach(T value, testContainer) {
231         cout << value << " ";
232     }
233
234     cout << endl;
235 }
236
237 template <typename Algorithm, typename DataType>
238 QList<ResultSet> testAlgorithm(Algorithm &algorithm,  QStringList dataSetTypes,  int size, int time)
239 {
240     QList<ResultSet> results;
241     foreach(QString dataSetType, dataSetTypes) {
242         QVector<DataType> container = generateData<DataType>(dataSetType, size);
243         results.append(testRun(container, algorithm, time));
244         if (!isSorted(container))
245             qWarning("%s: container is not sorted after test", Q_FUNC_INFO);
246     }
247     return results;
248 }
249
250 template <typename Algorithm, typename DataType>
251 void testAlgorithm(Algorithm algorithm, QStringList &dataSetTypes)
252 {
253     QList<int> sizes = QList<int>() << 5 << 15 << 35 << 70 << 200 << 1000 << 10000;
254     printHeader(dataSetTypes);
255     for (int s = 0; s < sizes.count(); ++s){
256         cout << setw(10) <<  setiosflags(ios_base::left)<< sizes.at(s);
257         QList<ResultSet> results =
258             testAlgorithm<Algorithm, DataType>(algorithm, dataSetTypes, sizes.at(s), 100);
259         foreach(ResultSet result, results) {
260             stringstream numSorts;
261             numSorts << setiosflags(ios_base::left) << setw(10) << result.numSorts;
262             stringstream lessThan;
263             lessThan << setiosflags(ios_base::left) << setw(10) << result.lessThanRefCount / result.numSorts;
264             cout << numSorts.str() << lessThan.str();
265         }
266         cout << endl;
267     }
268 }
269 #endif
270 static bool userFunction1(char ch1, char ch2)
271 {
272     return (ch1 ^ 1) < (ch2 ^ 1);
273 }
274
275 bool userFunction2(const char &ch1, char ch2)
276 {
277     return (ch1 ^ 1) < (ch2 ^ 1);
278 }
279
280 static inline bool userFunction3(char ch1, const char &ch2)
281 {
282     return (ch1 ^ 1) < (ch2 ^ 1);
283 }
284
285 inline bool userFunction4(const char &ch1, const char &ch2)
286 {
287     return (ch1 ^ 1) < (ch2 ^ 1);
288 }
289
290 class UserFunctor1
291 {
292 public:
293     UserFunctor1(int x = 1) : y(x) {}
294
295     bool operator()(char ch1, char ch2)
296     {
297         return (ch1 ^ y) < (ch2 ^ y);
298     }
299
300     char y;
301 };
302
303 void tst_QAlgorithms::qHeapSort()
304 {
305     char array1[] = "3141592";
306     ::qHeapSort((char *)array1, array1 + strlen(array1));
307     QVERIFY(strcmp(array1, "1123459") == 0);
308
309     ::qHeapSort((char *)array1, array1 + strlen(array1), qGreater<char>());
310     QVERIFY(strcmp(array1, "9543211") == 0);
311
312     ::qHeapSort((char *)array1, array1 + strlen(array1), qLess<char>());
313     QVERIFY(strcmp(array1, "1123459") == 0);
314     {
315         char array2[] = "0123456789@ABCDE";
316         ::qHeapSort((char *)array2, array2 + strlen(array2), userFunction1);
317         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
318     }
319
320     {
321         char array2[] = "0123456789@ABCDE";
322         ::qHeapSort((char *)array2, array2 + strlen(array2), userFunction2);
323         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
324     }
325
326     {
327         char array2[] = "0123456789@ABCDE";
328         ::qHeapSort((char *)array2, array2 + strlen(array2), userFunction3);
329         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
330     }
331
332     {
333         char array2[] = "0123456789@ABCDE";
334         ::qHeapSort((char *)array2, array2 + strlen(array2), userFunction4);
335         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
336     }
337
338     {
339         UserFunctor1 userFunctor1;
340         char array2[] = "0123456789@ABCDE";
341         ::qHeapSort((char *)array2, array2 + strlen(array2), userFunctor1);
342         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
343     }
344
345     {
346         char array2[] = "0123456789@ABCDE";
347         ::qHeapSort((char *)array2, array2 + strlen(array2), UserFunctor1());
348         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
349         ::qHeapSort((char *)array2, array2 + strlen(array2), UserFunctor1(1));
350         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
351         ::qHeapSort((char *)array2, array2 + strlen(array2), UserFunctor1(3));
352         QVERIFY(strcmp(array2, "3210765498CBA@ED") == 0);
353         ::qHeapSort((char *)array2, array2 + strlen(array2), UserFunctor1(0));
354         QVERIFY(strcmp(array2, "0123456789@ABCDE") == 0);
355     }
356 }
357
358 void tst_QAlgorithms::qBubbleSort()
359 {
360     char array1[] = "3141592";
361     ::qBubbleSort((char *)array1, array1 + strlen(array1));
362     QVERIFY(strcmp(array1, "1123459") == 0);
363
364     ::qBubbleSort((char *)array1, array1 + strlen(array1), qGreater<char>());
365     QVERIFY(strcmp(array1, "9543211") == 0);
366
367     ::qBubbleSort((char *)array1, array1 + strlen(array1), qLess<char>());
368     QVERIFY(strcmp(array1, "1123459") == 0);
369
370     {
371         char array2[] = "0123456789@ABCDE";
372         ::qBubbleSort((char *)array2, array2 + strlen(array2), userFunction1);
373         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
374     }
375
376     {
377         char array2[] = "0123456789@ABCDE";
378         ::qBubbleSort((char *)array2, array2 + strlen(array2), userFunction2);
379         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
380     }
381
382     {
383         char array2[] = "0123456789@ABCDE";
384         ::qBubbleSort((char *)array2, array2 + strlen(array2), userFunction3);
385         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
386     }
387
388     {
389         char array2[] = "0123456789@ABCDE";
390         ::qBubbleSort((char *)array2, array2 + strlen(array2), userFunction4);
391         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
392     }
393
394     {
395         UserFunctor1 userFunctor1;
396         char array2[] = "0123456789@ABCDE";
397         ::qBubbleSort((char *)array2, array2 + strlen(array2), userFunctor1);
398         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
399     }
400
401     {
402         char array2[] = "0123456789@ABCDE";
403         ::qBubbleSort((char *)array2, array2 + strlen(array2), UserFunctor1());
404         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
405         ::qBubbleSort((char *)array2, array2 + strlen(array2), UserFunctor1(1));
406         QVERIFY(strcmp(array2, "1032547698A@CBED") == 0);
407         ::qBubbleSort((char *)array2, array2 + strlen(array2), UserFunctor1(3));
408         QVERIFY(strcmp(array2, "3210765498CBA@ED") == 0);
409         ::qBubbleSort((char *)array2, array2 + strlen(array2), UserFunctor1(0));
410         QVERIFY(strcmp(array2, "0123456789@ABCDE") == 0);
411     }
412 }
413
414 void tst_QAlgorithms::swap()
415 {
416     {
417         int a = 1, b = 2;
418         qSwap(a, b);
419         QVERIFY(a == 2);
420         QVERIFY(b == 1);
421
422         qSwap(a, a);
423         QVERIFY(a == 2);
424         QVERIFY(b == 1);
425
426         qSwap(b, b);
427         QVERIFY(a == 2);
428         QVERIFY(b == 1);
429
430         qSwap(a, b);
431         QVERIFY(a == 1);
432         QVERIFY(b == 2);
433
434         qSwap(b, a);
435         QVERIFY(a == 2);
436         QVERIFY(b == 1);
437     }
438
439     {
440         double a = 1.0, b = 2.0;
441         qSwap(a, b);
442         QVERIFY(a == 2.0);
443         QVERIFY(b == 1.0);
444
445         qSwap(a, a);
446         QVERIFY(a == 2.0);
447         QVERIFY(b == 1.0);
448
449         qSwap(b, b);
450         QVERIFY(a == 2.0);
451         QVERIFY(b == 1.0);
452
453         qSwap(a, b);
454         QVERIFY(a == 1.0);
455         QVERIFY(b == 2.0);
456
457         qSwap(b, a);
458         QVERIFY(a == 2.0);
459         QVERIFY(b == 1.0);
460     }
461
462     {
463         QString a = "1", b = "2";
464         qSwap(a, b);
465         QVERIFY(a == "2");
466         QVERIFY(b == "1");
467
468         qSwap(a, a);
469         QVERIFY(a == "2");
470         QVERIFY(b == "1");
471
472         qSwap(b, b);
473         QVERIFY(a == "2");
474         QVERIFY(b == "1");
475
476         qSwap(a, b);
477         QVERIFY(a == "1");
478         QVERIFY(b == "2");
479
480         qSwap(b, a);
481         QVERIFY(a == "2");
482         QVERIFY(b == "1");
483     }
484
485     {
486         void *a = 0, *b = 0;
487         qSwap(a, b);
488     }
489
490     {
491         const void *a = 0, *b = 0;
492         qSwap(a, b);
493     }
494
495     {
496         QString *a = 0, *b = 0;
497         qSwap(a, b);
498     }
499
500     {
501         const QString *a = 0, *b = 0;
502         qSwap(a, b);
503     }
504
505     {
506         QString **a = 0, **b = 0;
507         qSwap(a, b);
508     }
509
510     {
511         const QString **a = 0, **b = 0;
512         qSwap(a, b);
513     }
514
515     {
516         QString * const *a = 0, * const *b = 0;
517         qSwap(a, b);
518     }
519
520     {
521         const QString * const *a = 0, * const *b = 0;
522         qSwap(a, b);
523     }
524 }
525
526 namespace SwapTest {
527     struct ST { int i; int j; };
528     void swap(ST &a, ST &b) {
529         a.i = b.j;
530         b.i = a.j;
531     }
532 }
533
534 void tst_QAlgorithms::swap2()
535 {
536     {
537 #ifndef QT_NO_SQL
538         //check the namespace lookup works correctly
539         SwapTest::ST a = { 45, 65 };
540         SwapTest::ST b = { 48, 68 };
541         qSwap(a, b);
542         QCOMPARE(a.i, 68);
543         QCOMPARE(b.i, 65);
544 #endif
545     }
546 }
547
548 void tst_QAlgorithms::sortEmptyList()
549 {
550     // Only test if it crashes
551     QStringList stringList;
552     stringList.sort();
553     QVERIFY(true);
554 }
555
556 void tst_QAlgorithms::sortedList()
557 {
558     QList<int> list;
559     list << 4 << 3 << 6;
560
561     ::qHeapSort(list.begin(), list.end());
562
563     QCOMPARE(list.count(), 3);
564     QCOMPARE(list.at(0), 3);
565     QCOMPARE(list.at(1), 4);
566     QCOMPARE(list.at(2), 6);
567
568     list.insert(qUpperBound(list.begin(), list.end(), 5), 5);
569     list.insert(qUpperBound(list.begin(), list.end(), 1), 1);
570     list.insert(qUpperBound(list.begin(), list.end(), 8), 8);
571
572     QCOMPARE(list.count(), 6);
573     QCOMPARE(list.at(0), 1);
574     QCOMPARE(list.at(1), 3);
575     QCOMPARE(list.at(2), 4);
576     QCOMPARE(list.at(3), 5);
577     QCOMPARE(list.at(4), 6);
578     QCOMPARE(list.at(5), 8);
579 }
580
581 Q_DECLARE_METATYPE(QList<int>)
582
583 void tst_QAlgorithms::test_qLowerBound_data()
584 {
585     QTest::addColumn<QList<int> >("data");
586     QTest::addColumn<int>("resultValue");
587     QTest::addColumn<int>("resultIndex");
588
589     QTest::newRow("sorted-duplicate") << (QList<int>() << 1 << 2 << 2 << 3) << 2 << 1;
590 }
591
592 void tst_QAlgorithms::test_qLowerBound()
593 {
594     QFETCH(QList<int>, data);
595     QFETCH(int, resultValue);
596     QFETCH(int, resultIndex);
597
598
599     QCOMPARE(qLowerBound(data.constBegin(), data.constEnd(), resultValue), data.constBegin() + resultIndex);
600     QCOMPARE(qLowerBound(data.begin(), data.end(), resultValue), data.begin() + resultIndex);
601     QCOMPARE(qLowerBound(data, resultValue), data.constBegin() + resultIndex);
602     QCOMPARE(qLowerBound(data.constBegin(), data.constEnd(), resultValue, qLess<int>()), data.constBegin() + resultIndex);
603 }
604
605 void tst_QAlgorithms::test_qUpperBound_data()
606 {
607     QTest::addColumn<QList<int> >("data");
608     QTest::addColumn<int>("resultValue");
609     QTest::addColumn<int>("resultIndex");
610
611     QTest::newRow("sorted-duplicate") << (QList<int>() << 1 << 2 << 2 << 3) << 2 << 3;
612 }
613
614 void tst_QAlgorithms::test_qUpperBound()
615 {
616     QFETCH(QList<int>, data);
617     QFETCH(int, resultValue);
618     QFETCH(int, resultIndex);
619
620     QCOMPARE(qUpperBound(data.constBegin(), data.constEnd(), resultValue), data.constBegin() + resultIndex);
621     QCOMPARE(qUpperBound(data.begin(), data.end(), resultValue), data.begin() + resultIndex);
622     QCOMPARE(qUpperBound(data, resultValue), data.constBegin() + resultIndex);
623     QCOMPARE(qUpperBound(data.constBegin(), data.constEnd(), resultValue, qLess<int>()), data.constBegin() + resultIndex);
624 }
625
626 void tst_QAlgorithms::test_qBinaryFind_data()
627 {
628     QTest::addColumn<QList<int> >("data");
629     QTest::addColumn<int>("resultValue"); // -42 means not found
630
631     QTest::newRow("sorted-duplicate") << (QList<int>() << 1 << 2 << 2 << 3) << 2;
632     QTest::newRow("sorted-end") << (QList<int>() << -5 << -2 << 0 << 8) << 8;
633     QTest::newRow("sorted-beginning") << (QList<int>() << -5 << -2 << 0 << 8) << -5;
634     QTest::newRow("sorted-duplicate-beginning") << (QList<int>() << -5 << -5 << -2 << 0 << 8) << -5;
635     QTest::newRow("empty") << (QList<int>()) << -42;
636     QTest::newRow("not found 1 ") << (QList<int>() << 1 << 5 << 8 << 65) << -42;
637     QTest::newRow("not found 2 ") << (QList<int>() << -456 << -5 << 8 << 65) << -42;
638 }
639
640 void tst_QAlgorithms::test_qBinaryFind()
641 {
642     QFETCH(QList<int>, data);
643     QFETCH(int, resultValue);
644
645     //-42 means not found
646     if (resultValue == -42) {
647         QVERIFY(qBinaryFind(data.constBegin(), data.constEnd(), resultValue) == data.constEnd());
648         QVERIFY(qBinaryFind(data, resultValue) == data.constEnd());
649         QVERIFY(qBinaryFind(data.begin(), data.end(), resultValue) == data.end());
650         QVERIFY(qBinaryFind(data.begin(), data.end(), resultValue, qLess<int>()) == data.end());
651         return;
652     }
653
654     QCOMPARE(*qBinaryFind(data.constBegin(), data.constEnd(), resultValue), resultValue);
655     QCOMPARE(*qBinaryFind(data.begin(), data.end(), resultValue), resultValue);
656     QCOMPARE(*qBinaryFind(data, resultValue), resultValue);
657     QCOMPARE(*qBinaryFind(data.constBegin(), data.constEnd(), resultValue, qLess<int>()), resultValue);
658 }
659
660 void tst_QAlgorithms::qBinaryFindOneEntry()
661 {
662     QList<int> list;
663     list << 2;
664
665     QVERIFY(::qBinaryFind(list.constBegin(), list.constEnd(), 2) != list.constEnd());
666 }
667
668
669 void tst_QAlgorithms::sortAPItest()
670 {
671     QVector<int> testVector = generateData<int>("Random", 101);
672     qSort(testVector);
673     QVERIFY(isSorted(testVector));
674     qSort(testVector.begin(), testVector.end());
675     QVERIFY(isSorted(testVector));
676     qSort(testVector.begin(), testVector.end(), qLess<int>());
677     QVERIFY(isSorted(testVector));
678
679     testVector = generateData<int>("Random", 71);
680     qStableSort(testVector);
681     QVERIFY(isSorted(testVector));
682     qStableSort(testVector.begin(), testVector.end());
683     QVERIFY(isSorted(testVector));
684     qStableSort(testVector.begin(), testVector.end(), qLess<int>());
685     QVERIFY(isSorted(testVector));
686
687     QList<int> testList = generateData<int>("Random", 101).toList();
688     qSort(testList);
689     QVERIFY(isSorted(testList));
690     qSort(testList.begin(), testList.end());
691     QVERIFY(isSorted(testList));
692     qSort(testList.begin(), testList.end(), qLess<int>());
693     QVERIFY(isSorted(testList));
694
695     testList = generateData<int>("Random", 71).toList();
696     qStableSort(testList);
697     QVERIFY(isSorted(testList));
698     qStableSort(testList.begin(), testList.end());
699     QVERIFY(isSorted(testList));
700     qStableSort(testList.begin(), testList.end(), qLess<int>());
701     QVERIFY(isSorted(testList));
702 }
703
704
705 class StableSortTest
706 {
707 public:
708     StableSortTest(){};
709     StableSortTest(int Major, int Minor) : Major(Major), Minor(Minor) {}
710     bool operator<(const StableSortTest &other) const {return (Major < other.Major); }
711     bool testMinor(const  StableSortTest &other) const {return  Minor < other.Minor; }
712
713 int Major;
714 int Minor;
715 };
716
717 ostream &operator<<(ostream &out, const StableSortTest& obj)  { out << obj.Major << "-" << obj.Minor; return out; }
718
719 QVector<StableSortTest> createStableTestVector()
720 {
721     QVector<StableSortTest> stableTestVector;
722         for (int i=500; i>=0; --i) {
723         for (int j=0; j<10; ++j) {
724             stableTestVector.append(StableSortTest(i, j));
725         }
726     }
727     return stableTestVector;
728 }
729
730 template <typename ContainerType, typename LessThan>
731 bool isStableSorted(ContainerType &container, LessThan lessThan)
732 {
733     for (int i=0; i < container.count() - 1; ++i) {
734         //not sorted?
735         if (lessThan(container.at(i + 1), container.at(i)))
736             return false;
737         // equal?
738         if (lessThan(container.at(i),  container.at(i + 1)))
739             continue;
740         // minor version?
741         if(container.at(i + 1).testMinor(container.at(i)))
742             return false;
743     }
744     return true;
745 }
746
747 void tst_QAlgorithms::stableSortTest()
748 {
749     // Selftests:
750     {
751         QVector<StableSortTest> stableTestVector = createStableTestVector();
752         qSort(stableTestVector.begin(), stableTestVector.end(), qLess<StableSortTest>());
753         QVERIFY(isSorted(stableTestVector, qLess<StableSortTest>()));
754         QVERIFY(!isStableSorted(stableTestVector, qLess<StableSortTest>()));
755     }
756     {
757         QVector<StableSortTest> stableTestVector = createStableTestVector();
758         qSort(stableTestVector.begin(), stableTestVector.end(), qGreater<StableSortTest>());
759         QVERIFY(isSorted(stableTestVector, qGreater<StableSortTest>()));
760         QVERIFY(!isStableSorted(stableTestVector, qGreater<StableSortTest>()));
761     }
762     {
763         QVector<StableSortTest> stableTestVector = createStableTestVector();
764         qSort(stableTestVector.begin(), stableTestVector.end(), qGreater<StableSortTest>());
765         QVERIFY(!isSorted(stableTestVector, qLess<StableSortTest>()));
766         QVERIFY(!isStableSorted(stableTestVector, qGreater<StableSortTest>()));
767     }
768
769
770     // Stable sort with qLess
771     {
772         QVector<StableSortTest> stableTestVector = createStableTestVector();
773         std::stable_sort(stableTestVector.begin(), stableTestVector.end(), qLess<StableSortTest>());
774         QVERIFY(isSorted(stableTestVector, qLess<StableSortTest>()));
775         QVERIFY(isStableSorted(stableTestVector, qLess<StableSortTest>()));
776     }
777     {
778         QVector<StableSortTest> stableTestVector = createStableTestVector();
779         qStableSort(stableTestVector.begin(), stableTestVector.end(), qLess<StableSortTest>());
780         QVERIFY(isSorted(stableTestVector, qLess<StableSortTest>()));
781         QVERIFY(isStableSorted(stableTestVector, qLess<StableSortTest>()));
782     }
783
784     // Stable sort with qGreater
785     {
786         QVector<StableSortTest> stableTestVector = createStableTestVector();
787         std::stable_sort(stableTestVector.begin(), stableTestVector.end(), qGreater<StableSortTest>());
788         QVERIFY(isSorted(stableTestVector, qGreater<StableSortTest>()));
789         QVERIFY(isStableSorted(stableTestVector, qGreater<StableSortTest>()));
790     }
791
792     {
793         QVector<StableSortTest> stableTestVector = createStableTestVector();
794         qStableSort(stableTestVector.begin(), stableTestVector.end(), qGreater<StableSortTest>());
795         QVERIFY(isSorted(stableTestVector, qGreater<StableSortTest>()));
796         QVERIFY(isStableSorted(stableTestVector, qGreater<StableSortTest>()));
797     }
798 }
799
800 Q_DECLARE_METATYPE(QVector<int>)
801
802 void tst_QAlgorithms::stableSortCorrectnessTest_data()
803 {
804     const int dataSize = 1000;
805     QTest::addColumn<QVector<int> >("unsorted");
806     QTest::newRow("From documentation") << (QVector<int>() << 33 << 12 << 68 << 6 << 12);
807     QTest::newRow("Equal") << (generateData<int>("Equal", dataSize));
808     QTest::newRow("Ascending") << (generateData<int>("Ascending", dataSize));
809     QTest::newRow("Descending") << (generateData<int>("Descending", dataSize));
810     QTest::newRow("Duplicates") << (generateData<int>("Duplicates", dataSize));
811     QTest::newRow("Almost Sorted") << (generateData<int>("Almost Sorted", dataSize));
812     QTest::newRow("Random") << (generateData<int>("Random", dataSize));
813 }
814
815 void tst_QAlgorithms::stableSortCorrectnessTest()
816 {
817     QFETCH(QVector<int>, unsorted);
818
819     QVector<int> sorted = unsorted;
820     qStableSort(sorted.begin(), sorted.end());
821
822     // Verify that sorted contains the same numbers as unsorted.
823     foreach(int value, unsorted) {
824         QVERIFY(sorted.contains(value));
825         int unsortedCount = 0;
826         qCount(unsorted.begin(), unsorted.end(), value, unsortedCount);
827         int sortedCount = 0;
828         qCount(sorted.begin(), sorted.end(), value, sortedCount);
829         QCOMPARE(sortedCount, unsortedCount);
830     }
831
832     QVERIFY(isSorted(sorted));
833 }
834
835 void tst_QAlgorithms::convenienceAPI()
836 {
837     // Compile-test for QAlgorithm convenience functions.
838     QList<int> list, list2;
839
840     qCopy(list.begin(), list.end(), list2.begin());
841     qCopyBackward(list.begin(), list.end(), list2.begin());
842     qEqual(list.begin(), list.end(), list2.begin());
843
844     qFill(list, 1);
845     qFill(list.begin(), list.end(), 1);
846
847     qFind(list, 1);
848     qFind(list.begin(), list.end(), 1);
849
850     int count1 = 0 , count2 = 0, count3 = 0;
851     qCount(list, 1, count1);
852     qCount(list.begin(), list.end(), 1, count2);
853     QCOMPARE(count1, count2);
854     QCOMPARE(count2, count3);
855
856     qSort(list);
857     qSort(list.begin(), list.end());
858     qSort(list.begin(), list.end(), qLess<int>());
859
860     qStableSort(list);
861     qStableSort(list.begin(), list.end());
862     qStableSort(list.begin(), list.end(), qLess<int>());
863
864     qLowerBound(list, 1);;
865     qLowerBound(list.begin(), list.end(),  1);
866     qLowerBound(list.begin(), list.end(), 1, qLess<int>());
867
868     qUpperBound(list, 1);
869     qUpperBound(list.begin(), list.end(),  1);
870     qUpperBound(list.begin(), list.end(), 1, qLess<int>());
871
872     qBinaryFind(list, 1);
873     qBinaryFind(list.begin(), list.end(),  1);
874     qBinaryFind(list.begin(), list.end(), 1, qLess<int>());
875
876     QList<int *> pointerList;
877     qDeleteAll(pointerList);
878     qDeleteAll(pointerList.begin(), pointerList.end());
879 }
880
881 template <typename DataType>
882 class HeapSortHelper
883 {
884 public:
885     void operator()(QVector<DataType> list)
886     {
887         ::qHeapSort(list);
888     }
889 };
890
891 template <typename DataType>
892 class BubbleSortHelper
893 {
894 public:
895     void operator()(QVector<DataType> list)
896     {
897         ::qBubbleSort(list);
898     }
899 };
900
901 template <typename DataType>
902 class QuickSortHelper
903 {
904 public:
905     void operator()(QVector<DataType> list)
906     {
907         ::qSort(list);
908     }
909 };
910
911 template <typename DataType>
912 class StableSortHelper
913 {
914 public:
915     void operator()(QVector<DataType> list)
916     {
917         ::qStableSort(list);
918     }
919 };
920
921 template <typename DataType>
922 class StlSortHelper
923 {
924 public:
925     void operator()(QVector<DataType> list)
926     {
927         std::sort(list.begin(), list.end());
928     }
929 };
930
931 template <typename DataType>
932 class StlStableSortHelper
933 {
934 public:
935     void operator()(QVector<DataType> list)
936     {
937         std::stable_sort(list.begin(), list.end());
938     }
939 };
940
941 #if Q_TEST_PERFORMANCE
942 void tst_QAlgorithms::performance()
943 {
944     cout << endl << "Quick sort" << endl;
945     testAlgorithm<QuickSortHelper<TestInt>, TestInt>(QuickSortHelper<TestInt>(), dataSetTypes);
946     cout << endl << "stable sort" << endl;
947     testAlgorithm<StableSortHelper<TestInt>, TestInt>(StableSortHelper<TestInt>(), dataSetTypes);
948     cout << endl << "std::sort" << endl;
949     testAlgorithm<StlSortHelper<TestInt>, TestInt>(StlSortHelper<TestInt>(), dataSetTypes);
950     cout << endl << "std::stable_sort" << endl;
951     testAlgorithm<StlStableSortHelper<TestInt>, TestInt>(StlStableSortHelper<TestInt>(), dataSetTypes);
952     cout << "Heap sort" << endl;
953     testAlgorithm<HeapSortHelper<TestInt>, TestInt>(HeapSortHelper<TestInt>(), dataSetTypes);
954     cout << endl << "Bubble sort" << endl;
955     testAlgorithm<BubbleSortHelper<TestInt>, TestInt>(BubbleSortHelper<TestInt>(), dataSetTypes);
956 /*
957     cout << endl << "Sorting lists of ints" << endl;
958     cout << "Heap sort" << endl;
959     testAlgorithm<HeapSortHelper<int>, int>(HeapSortHelper<int>(), dataSetTypes);
960     cout << endl << "Quick sort" << endl;
961     testAlgorithm<QuickSortHelper<int>, int>(QuickSortHelper<int>(), dataSetTypes);
962     cout << endl << "std::sort" << endl;
963     testAlgorithm<StlSortHelper<int>, int>(StlSortHelper<int>(), dataSetTypes);
964     cout << endl << "std::stable_sort" << endl;
965     testAlgorithm<StlStableSortHelper<int>, int>(StlStableSortHelper<int>(), dataSetTypes);
966     cout << endl << "Bubble sort" << endl;
967     testAlgorithm<BubbleSortHelper<int>, int>(BubbleSortHelper<int>(), dataSetTypes);
968 */
969 }
970 #endif
971
972 void tst_QAlgorithms::qCountIterators() const
973 {
974     QList<int> list;
975     list << 3 << 3 << 6 << 6 << 6 << 8;
976
977     {
978         int countOf7 = 0;
979         ::qCount(list.begin(), list.end(), 7, countOf7);
980         QCOMPARE(countOf7, 0);
981     }
982
983     {
984         int countOf3 = 0;
985         ::qCount(list.begin(), list.end(), 3, countOf3);
986         QCOMPARE(countOf3, 2);
987     }
988
989     {
990         int countOf6 = 0;
991         ::qCount(list.begin(), list.end(), 6, countOf6);
992         QCOMPARE(countOf6, 3);
993     }
994
995     {
996         int countOf8 = 0;
997         ::qCount(list.begin(), list.end(), 8, countOf8);
998         QCOMPARE(countOf8, 1);
999     }
1000
1001     /* Check that we add to the count, not set it. */
1002     {
1003         int countOf8 = 5;
1004         ::qCount(list.begin(), list.end(), 8, countOf8);
1005         QCOMPARE(countOf8, 6);
1006     }
1007 }
1008
1009 void tst_QAlgorithms::qCountContainer() const
1010 {
1011     QList<int> list;
1012     list << 3 << 3 << 6 << 6 << 6 << 8;
1013
1014     {
1015         int countOf7 = 0;
1016         ::qCount(list, 7, countOf7);
1017         QCOMPARE(countOf7, 0);
1018     }
1019
1020     {
1021         int countOf3 = 0;
1022         ::qCount(list, 3, countOf3);
1023         QCOMPARE(countOf3, 2);
1024     }
1025
1026     {
1027         int countOf6 = 0;
1028         ::qCount(list, 6, countOf6);
1029         QCOMPARE(countOf6, 3);
1030     }
1031
1032     {
1033         int countOf8 = 0;
1034         ::qCount(list, 8, countOf8);
1035         QCOMPARE(countOf8, 1);
1036     }
1037
1038     /* Check that we add to the count, not set it. */
1039     {
1040         int countOf8 = 5;
1041         ::qCount(list, 8, countOf8);
1042         QCOMPARE(countOf8, 6);
1043     }
1044 }
1045
1046 class RAI
1047 {
1048   public:
1049     RAI(int searched = 5, int hidePos = 4, int len = 10)
1050         : curPos_(0)
1051         , length_(len)
1052         , searchedVal_(searched)
1053         , searchedValPos_(hidePos)
1054     {
1055     }
1056
1057     int at(int pos) const
1058     {
1059         if (pos == searchedValPos_) {
1060             return searchedVal_;
1061         }
1062         else if (pos < searchedValPos_) {
1063             return searchedVal_ - 1;
1064         }
1065
1066         return searchedVal_ + 1;
1067     }
1068
1069     RAI begin() const
1070     {
1071         RAI rai = *this;
1072         rai.setCurPos(0);
1073         return rai;
1074     }
1075
1076     RAI end() const
1077     {
1078         RAI rai = *this;
1079         rai.setCurPos(length_);
1080         return rai;
1081     }
1082
1083     int pos() const
1084     {
1085         return curPos();
1086     }
1087
1088     int size() const
1089     {
1090         return length_;
1091     }
1092
1093     RAI operator+(int i) const
1094     {
1095         RAI rai = *this;
1096         rai.setCurPos( rai.curPos() + i );
1097         if (rai.curPos() > length_) {
1098             rai.setCurPos(length_);
1099         }
1100         return rai;
1101     }
1102
1103     RAI operator-(int i) const
1104     {
1105         RAI rai = *this;
1106         rai.setCurPos( rai.curPos() - i );
1107         if (rai.curPos() < 0) {
1108             rai.setCurPos(0);
1109         }
1110         return rai;
1111     }
1112
1113     int operator-(const RAI& it) const
1114     {
1115         return curPos() - it.curPos();
1116     }
1117
1118     RAI& operator+=(int i)
1119     {
1120         setCurPos( curPos() + i );
1121         if (curPos() > length_) {
1122             setCurPos(length_);
1123         }
1124         return *this;
1125     }
1126
1127     RAI& operator-=(int i)
1128     {
1129         setCurPos( curPos() - i);
1130         if (curPos() < 0) {
1131             setCurPos(0);
1132         }
1133         return *this;
1134     }
1135
1136     RAI& operator++()
1137     {
1138         if (curPos() < length_) {
1139             setCurPos( curPos() + 1 );
1140         }
1141         return *this;
1142     }
1143
1144     RAI operator++(int)
1145     {
1146         RAI rai = *this;
1147
1148         if (curPos() < length_) {
1149             setCurPos( curPos() + 1 );
1150         }
1151
1152         return rai;
1153     }
1154
1155     RAI& operator--()
1156     {
1157         if (curPos() > 0) {
1158             setCurPos( curPos() - 1 );
1159         }
1160         return *this;
1161     }
1162
1163     RAI operator--(int)
1164     {
1165         RAI rai = *this;
1166
1167         if (curPos() > 0) {
1168             setCurPos( curPos() - 1 );
1169         }
1170
1171         return rai;
1172     }
1173
1174     bool operator==(const RAI& rai) const
1175     {
1176         return rai.curPos() == curPos();
1177     }
1178
1179     bool operator!=(const RAI& rai) const
1180     {
1181         return !operator==(rai);
1182     }
1183
1184     int operator*() const
1185     {
1186         return at(curPos());
1187     }
1188
1189     int operator[](int i) const
1190     {
1191         return at(i);
1192     }
1193
1194   private:
1195
1196     int curPos() const
1197     {
1198         return curPos_;
1199     }
1200
1201     void setCurPos(int pos)
1202     {
1203         curPos_ = pos;
1204     }
1205
1206     int curPos_;
1207     int length_;
1208     int searchedVal_;
1209     int searchedValPos_;
1210 };
1211
1212 void tst_QAlgorithms::binaryFindOnLargeContainer() const
1213 {
1214   const int len = 2 * 1000 * 1000 * 537;
1215   const int pos = len - 12345;
1216   RAI rai(5, pos, len);
1217
1218   RAI foundIt = qBinaryFind(rai.begin(), rai.end(), 5);
1219   QCOMPARE(foundIt.pos(), 1073987655);
1220 }
1221
1222 QTEST_APPLESS_MAIN(tst_QAlgorithms)
1223 #include "tst_qalgorithms.moc"
1224