1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtCore/QCoreApplication>
31#include <QtTest/QtTest>
32#ifdef QT_GUI_LIB
33#include <QtGui/QColor>
34#include <QtGui/QImage>
35#include <QtGui/QPixmap>
36#include <QtGui/QVector2D>
37#include <QtGui/QVector3D>
38#include <QtGui/QVector4D>
39#endif
40
41/* XPM test data for QPixmap, QImage tests (use drag cursors as example) */
42
43static const char * const xpmPixmapData1[] = {
44"11 20 3 1",
45". c None",
46"a c #FFFFFF",
47"X c #000000", // X11 cursor is traditionally black
48"aa.........",
49"aXa........",
50"aXXa.......",
51"aXXXa......",
52"aXXXXa.....",
53"aXXXXXa....",
54"aXXXXXXa...",
55"aXXXXXXXa..",
56"aXXXXXXXXa.",
57"aXXXXXXXXXa",
58"aXXXXXXaaaa",
59"aXXXaXXa...",
60"aXXaaXXa...",
61"aXa..aXXa..",
62"aa...aXXa..",
63"a.....aXXa.",
64"......aXXa.",
65".......aXXa",
66".......aXXa",
67"........aa."};
68
69static const char * const xpmPixmapData2[] = {
70"11 20 4 1",
71". c None",
72"a c #FFFFFF",
73"b c #0000FF",
74"X c #000000",
75"aab........",
76"aXab.......",
77"aXXab......",
78"aXXXab.....",
79"aXXXXab....",
80"aXXXXXab...",
81"aXXXXXXab..",
82"aXXXXXXXa..",
83"aXXXXXXXXa.",
84"aXXXXXXXXXa",
85"aXXXXXXaaaa",
86"aXXXaXXa...",
87"aXXaaXXa...",
88"aXa..aXXa..",
89"aa...aXXa..",
90"a.....aXXa.",
91"......aXXa.",
92".......aXXa",
93".......aXXa",
94"........aa."};
95
96static const char * const xpmPixmapData3[] = {
97"20 20 2 1",
98" c #000000",
99". c #C32D2D",
100" ..........",
101" ........",
102" .......",
103" ......",
104" ....",
105" ..",
106" .",
107" ",
108" ",
109". ",
110"... ",
111"..... ",
112"...... ",
113"....... ",
114"......... ",
115"........... ",
116"........... ",
117"............ ",
118"............ ",
119"............. "};
120
121class tst_Cmptest: public QObject
122{
123 Q_OBJECT
124
125public:
126 enum class MyClassEnum { MyClassEnumValue1, MyClassEnumValue2 };
127 Q_ENUM(MyClassEnum)
128
129private slots:
130 void compare_unregistered_enums();
131 void compare_registered_enums();
132 void compare_class_enums();
133 void test_windowflags_data();
134 void test_windowflags();
135 void test_unregistered_flags_data();
136 void test_unregistered_flags();
137 void compare_boolfuncs();
138 void compare_to_nullptr();
139 void compare_pointerfuncs();
140 void compare_tostring();
141 void compare_tostring_data();
142 void compareQStringLists();
143 void compareQStringLists_data();
144 void compareQListInt();
145 void compareQListDouble();
146#ifdef QT_GUI_LIB
147 void compareQColor_data();
148 void compareQColor();
149 void compareQPixmaps();
150 void compareQPixmaps_data();
151 void compareQImages();
152 void compareQImages_data();
153 void compareQRegion_data();
154 void compareQRegion();
155 void compareQVector2D();
156 void compareQVector3D();
157 void compareQVector4D();
158#endif
159 void verify();
160 void verify2();
161 void tryVerify();
162 void tryVerify2();
163 void verifyExplicitOperatorBool();
164};
165
166enum MyUnregisteredEnum { MyUnregisteredEnumValue1, MyUnregisteredEnumValue2 };
167
168void tst_Cmptest::compare_unregistered_enums()
169{
170 QCOMPARE(MyUnregisteredEnumValue1, MyUnregisteredEnumValue1);
171 QCOMPARE(MyUnregisteredEnumValue1, MyUnregisteredEnumValue2);
172}
173
174void tst_Cmptest::compare_registered_enums()
175{
176 // use an enum that doesn't start at 0
177 QCOMPARE(Qt::Monday, Qt::Monday);
178 QCOMPARE(Qt::Monday, Qt::Sunday);
179}
180
181void tst_Cmptest::compare_class_enums()
182{
183 QCOMPARE(MyClassEnum::MyClassEnumValue1, MyClassEnum::MyClassEnumValue1);
184 QCOMPARE(MyClassEnum::MyClassEnumValue1, MyClassEnum::MyClassEnumValue2);
185}
186
187void tst_Cmptest::test_windowflags_data()
188{
189 QTest::addColumn<Qt::WindowFlags>(name: "actualWindowFlags");
190 QTest::addColumn<Qt::WindowFlags>(name: "expectedWindowFlags");
191
192 const Qt::WindowFlags windowFlags = Qt::Window
193 | Qt::WindowSystemMenuHint | Qt::WindowStaysOnBottomHint;
194 QTest::newRow(dataTag: "pass")
195 << windowFlags
196 << windowFlags;
197 QTest::newRow(dataTag: "fail1")
198 << windowFlags
199 << (windowFlags | Qt::FramelessWindowHint);
200 QTest::newRow(dataTag: "fail2")
201 << Qt::WindowFlags(Qt::Window)
202 << Qt::WindowFlags(Qt::Window | Qt::FramelessWindowHint);
203}
204
205void tst_Cmptest::test_windowflags()
206{
207 QFETCH(Qt::WindowFlags, actualWindowFlags);
208 QFETCH(Qt::WindowFlags, expectedWindowFlags);
209 QCOMPARE(actualWindowFlags, expectedWindowFlags);
210}
211
212enum UnregisteredEnum {
213 UnregisteredEnumValue1 = 0x1,
214 UnregisteredEnumValue2 = 0x2,
215 UnregisteredEnumValue3 = 0x4
216};
217
218typedef QFlags<UnregisteredEnum> UnregisteredFlags;
219
220Q_DECLARE_METATYPE(UnregisteredFlags);
221
222void tst_Cmptest::test_unregistered_flags_data()
223{
224 QTest::addColumn<UnregisteredFlags>(name: "actualFlags");
225 QTest::addColumn<UnregisteredFlags>(name: "expectedFlags");
226
227 QTest::newRow(dataTag: "pass")
228 << UnregisteredFlags(UnregisteredEnumValue1)
229 << UnregisteredFlags(UnregisteredEnumValue1);
230 QTest::newRow(dataTag: "fail1")
231 << UnregisteredFlags(UnregisteredEnumValue1 | UnregisteredEnumValue2)
232 << UnregisteredFlags(UnregisteredEnumValue1 | UnregisteredEnumValue3);
233 QTest::newRow(dataTag: "fail2")
234 << UnregisteredFlags(UnregisteredEnumValue1)
235 << UnregisteredFlags(UnregisteredEnumValue1 | UnregisteredEnumValue3);
236}
237
238void tst_Cmptest::test_unregistered_flags()
239{
240 QFETCH(UnregisteredFlags, actualFlags);
241 QFETCH(UnregisteredFlags, expectedFlags);
242 QCOMPARE(actualFlags, expectedFlags);
243}
244
245static bool boolfunc() { return true; }
246static bool boolfunc2() { return true; }
247
248void tst_Cmptest::compare_boolfuncs()
249{
250 QCOMPARE(boolfunc(), boolfunc());
251 QCOMPARE(boolfunc(), boolfunc2());
252 QCOMPARE(!boolfunc(), !boolfunc2());
253 QCOMPARE(boolfunc(), true);
254 QCOMPARE(!boolfunc(), false);
255}
256
257namespace {
258template <typename T>
259T *null() noexcept { return nullptr; }
260}
261
262void tst_Cmptest::compare_to_nullptr()
263{
264 QCOMPARE(null<int>(), nullptr);
265 QCOMPARE(null<const int>(), nullptr);
266 QCOMPARE(null<volatile int>(), nullptr);
267 QCOMPARE(null<const volatile int>(), nullptr);
268
269 QCOMPARE(nullptr, null<int>());
270 QCOMPARE(nullptr, null<const int>());
271 QCOMPARE(nullptr, null<volatile int>());
272 QCOMPARE(nullptr, null<const volatile int>());
273}
274
275static int i = 0;
276
277static int *intptr() { return &i; }
278
279void tst_Cmptest::compare_pointerfuncs()
280{
281 QCOMPARE(intptr(), intptr());
282 QCOMPARE(&i, &i);
283 QCOMPARE(intptr(), &i);
284 QCOMPARE(&i, intptr());
285}
286
287
288struct PhonyClass
289{
290 int i;
291};
292
293void tst_Cmptest::compare_tostring_data()
294{
295 QTest::addColumn<QVariant>(name: "actual");
296 QTest::addColumn<QVariant>(name: "expected");
297
298 QTest::newRow(dataTag: "int, string")
299 << QVariant::fromValue(value: 123)
300 << QVariant::fromValue(value: QString("hi"))
301 ;
302
303 QTest::newRow(dataTag: "both invalid")
304 << QVariant()
305 << QVariant()
306 ;
307
308 QTest::newRow(dataTag: "null hash, invalid")
309 << QVariant(QVariant::Hash)
310 << QVariant()
311 ;
312
313 QTest::newRow(dataTag: "string, null user type")
314 << QVariant::fromValue(value: QString::fromLatin1(str: "A simple string"))
315 << QVariant(QVariant::Type(qRegisterMetaType<PhonyClass>(typeName: "PhonyClass")))
316 ;
317
318 PhonyClass fake1 = {.i: 1};
319 PhonyClass fake2 = {.i: 2};
320 QTest::newRow(dataTag: "both non-null user type")
321 << QVariant(qRegisterMetaType<PhonyClass>(typeName: "PhonyClass"), (const void*)&fake1)
322 << QVariant(qRegisterMetaType<PhonyClass>(typeName: "PhonyClass"), (const void*)&fake2)
323 ;
324}
325
326void tst_Cmptest::compare_tostring()
327{
328 QFETCH(QVariant, actual);
329 QFETCH(QVariant, expected);
330
331 QCOMPARE(actual, expected);
332}
333
334void tst_Cmptest::compareQStringLists_data()
335{
336 QTest::addColumn<QStringList>(name: "opA");
337 QTest::addColumn<QStringList>(name: "opB");
338
339 {
340 QStringList opA;
341 QStringList opB(opA);
342
343 QTest::newRow(dataTag: "empty lists") << opA << opB;
344 }
345
346 {
347 QStringList opA;
348 opA.append(t: QLatin1String("string1"));
349 opA.append(t: QLatin1String("string2"));
350 opA.append(t: QLatin1String("string3"));
351 opA.append(t: QLatin1String("string4"));
352
353 QStringList opB(opA);
354
355 QTest::newRow(dataTag: "equal lists") << opA << opB;
356 }
357
358 {
359 QStringList opA;
360 opA.append(t: QLatin1String("string1"));
361 opA.append(t: QLatin1String("string2"));
362
363 QStringList opB(opA);
364 opA.append(t: QLatin1String("string3"));
365 opB.append(t: QLatin1String("DIFFERS"));
366
367 QTest::newRow(dataTag: "last item different") << opA << opB;
368 }
369
370 {
371 QStringList opA;
372 opA.append(t: QLatin1String("string1"));
373 opA.append(t: QLatin1String("string2"));
374
375 QStringList opB(opA);
376 opA.append(t: QLatin1String("string3"));
377 opA.append(t: QLatin1String("string4"));
378
379 opB.append(t: QLatin1String("DIFFERS"));
380 opB.append(t: QLatin1String("string4"));
381
382 QTest::newRow(dataTag: "second-last item different") << opA << opB;
383 }
384
385 {
386 QStringList opA;
387 opA.append(t: QLatin1String("string1"));
388 opA.append(t: QLatin1String("string2"));
389
390 QStringList opB;
391 opB.append(t: QLatin1String("string1"));
392
393 QTest::newRow(dataTag: "prefix") << opA << opB;
394 }
395
396 {
397 QStringList opA;
398 opA.append(t: QLatin1String("openInNewWindow"));
399 opA.append(t: QLatin1String("openInNewTab"));
400 opA.append(t: QLatin1String("separator"));
401 opA.append(t: QLatin1String("bookmark_add"));
402 opA.append(t: QLatin1String("savelinkas"));
403 opA.append(t: QLatin1String("copylinklocation"));
404 opA.append(t: QLatin1String("separator"));
405 opA.append(t: QLatin1String("openWith_submenu"));
406 opA.append(t: QLatin1String("preview1"));
407 opA.append(t: QLatin1String("actions_submenu"));
408 opA.append(t: QLatin1String("separator"));
409 opA.append(t: QLatin1String("viewDocumentSource"));
410
411 QStringList opB;
412 opB.append(t: QLatin1String("viewDocumentSource"));
413
414 QTest::newRow(dataTag: "short list second") << opA << opB;
415
416 QTest::newRow(dataTag: "short list first") << opB << opA;
417 }
418}
419
420void tst_Cmptest::compareQStringLists()
421{
422 QFETCH(QStringList, opA);
423 QFETCH(QStringList, opB);
424
425 QCOMPARE(opA, opB);
426}
427
428void tst_Cmptest::compareQListInt()
429{
430 QList<int> int1; int1 << 1 << 2 << 3;
431 QList<int> int2; int2 << 1 << 2 << 4;
432 QCOMPARE(int1, int2);
433}
434
435void tst_Cmptest::compareQListDouble()
436{
437 QList<double> double1; double1 << 1.5 << 2 << 3;
438 QList<double> double2; double2 << 1 << 2 << 4;
439 QCOMPARE(double1, double2);
440}
441
442#ifdef QT_GUI_LIB
443void tst_Cmptest::compareQColor_data()
444{
445 QTest::addColumn<QColor>(name: "colorA");
446 QTest::addColumn<QColor>(name: "colorB");
447
448 QTest::newRow(dataTag: "Qt::yellow vs \"yellow\"") << QColor(Qt::yellow) << QColor(QStringLiteral("yellow"));
449 QTest::newRow(dataTag: "Qt::yellow vs Qt::green") << QColor(Qt::yellow) << QColor(Qt::green);
450 QTest::newRow(dataTag: "0x88ff0000 vs 0xffff0000") << QColor::fromRgba(rgba: 0x88ff0000) << QColor::fromRgba(rgba: 0xffff0000);
451}
452
453void tst_Cmptest::compareQColor()
454{
455 QFETCH(QColor, colorA);
456 QFETCH(QColor, colorB);
457
458 QCOMPARE(colorA, colorB);
459}
460
461void tst_Cmptest::compareQPixmaps_data()
462{
463 QTest::addColumn<QPixmap>(name: "opA");
464 QTest::addColumn<QPixmap>(name: "opB");
465
466 const QPixmap pixmap1(xpmPixmapData1);
467 const QPixmap pixmap2(xpmPixmapData2);
468 const QPixmap pixmap3(xpmPixmapData3);
469 QPixmap pixmapWrongDpr = pixmap1.scaled(w: 2, h: 2);
470 pixmapWrongDpr.setDevicePixelRatio(2);
471
472 QTest::newRow(dataTag: "both null") << QPixmap() << QPixmap();
473 QTest::newRow(dataTag: "one null") << QPixmap() << pixmap1;
474 QTest::newRow(dataTag: "other null") << pixmap1 << QPixmap();
475 QTest::newRow(dataTag: "equal") << pixmap1 << pixmap1;
476 QTest::newRow(dataTag: "different size") << pixmap1 << pixmap3;
477 QTest::newRow(dataTag: "different pixels") << pixmap1 << pixmap2;
478 QTest::newRow(dataTag: "different dpr") << pixmap1 << pixmapWrongDpr;
479}
480
481void tst_Cmptest::compareQPixmaps()
482{
483 QFETCH(QPixmap, opA);
484 QFETCH(QPixmap, opB);
485
486 QCOMPARE(opA, opB);
487}
488
489void tst_Cmptest::compareQImages_data()
490{
491 QTest::addColumn<QImage>(name: "opA");
492 QTest::addColumn<QImage>(name: "opB");
493
494 const QImage image1(QPixmap(xpmPixmapData1).toImage());
495 const QImage image2(QPixmap(xpmPixmapData2).toImage());
496 const QImage image1Indexed = image1.convertToFormat(f: QImage::Format_Indexed8);
497 const QImage image3(QPixmap(xpmPixmapData3).toImage());
498 QImage imageWrongDpr = image1.scaled(w: 2, h: 2);
499 imageWrongDpr.setDevicePixelRatio(2);
500
501 QTest::newRow(dataTag: "both null") << QImage() << QImage();
502 QTest::newRow(dataTag: "one null") << QImage() << image1;
503 QTest::newRow(dataTag: "other null") << image1 << QImage();
504 QTest::newRow(dataTag: "equal") << image1 << image1;
505 QTest::newRow(dataTag: "different size") << image1 << image3;
506 QTest::newRow(dataTag: "different format") << image1 << image1Indexed;
507 QTest::newRow(dataTag: "different pixels") << image1 << image2;
508 QTest::newRow(dataTag: "different dpr") << image1 << imageWrongDpr;
509}
510
511void tst_Cmptest::compareQImages()
512{
513 QFETCH(QImage, opA);
514 QFETCH(QImage, opB);
515
516 QCOMPARE(opA, opB);
517}
518
519void tst_Cmptest::compareQRegion_data()
520{
521 QTest::addColumn<QRegion>(name: "rA");
522 QTest::addColumn<QRegion>(name: "rB");
523 const QRect rect1(QPoint(10, 10), QSize(200, 50));
524 const QRegion region1(rect1);
525 QRegion listRegion2;
526 const QVector<QRect> list2 = QVector<QRect>() << QRect(QPoint(100, 200), QSize(50, 200)) << rect1;
527 listRegion2.setRects(rect: list2.constData(), num: list2.size());
528 QTest::newRow(dataTag: "equal-empty") << QRegion() << QRegion();
529 QTest::newRow(dataTag: "1-empty") << region1 << QRegion();
530 QTest::newRow(dataTag: "equal") << region1 << region1;
531 QTest::newRow(dataTag: "different lists") << region1 << listRegion2;
532}
533
534void tst_Cmptest::compareQRegion()
535{
536 QFETCH(QRegion, rA);
537 QFETCH(QRegion, rB);
538
539 QCOMPARE(rA, rB);
540}
541
542void tst_Cmptest::compareQVector2D()
543{
544 QVector2D v2a{1, 2};
545 QVector2D v2b = v2a;
546 QCOMPARE(v2a, v2b);
547 v2b.setY(3);
548 QCOMPARE(v2a, v2b);
549}
550
551void tst_Cmptest::compareQVector3D()
552{
553 QVector3D v3a{1, 2, 3};
554 QVector3D v3b = v3a;
555 QCOMPARE(v3a, v3b);
556 v3b.setY(3);
557 QCOMPARE(v3a, v3b);
558}
559
560void tst_Cmptest::compareQVector4D()
561{
562 QVector4D v4a{1, 2, 3, 4};
563 QVector4D v4b = v4a;
564 QCOMPARE(v4a, v4b);
565 v4b.setY(3);
566 QCOMPARE(v4a, v4b);
567}
568#endif // QT_GUI_LIB
569
570static int opaqueFunc()
571{
572 return 42;
573}
574
575void tst_Cmptest::verify()
576{
577 QVERIFY(opaqueFunc() > 2);
578 QVERIFY(opaqueFunc() < 2);
579}
580
581void tst_Cmptest::verify2()
582{
583 QVERIFY2(opaqueFunc() > 2, QByteArray::number(opaqueFunc()).constData());
584 QVERIFY2(opaqueFunc() < 2, QByteArray::number(opaqueFunc()).constData());
585}
586
587void tst_Cmptest::tryVerify()
588{
589 QTRY_VERIFY(opaqueFunc() > 2);
590 QTRY_VERIFY_WITH_TIMEOUT(opaqueFunc() < 2, 1);
591}
592
593void tst_Cmptest::tryVerify2()
594{
595 QTRY_VERIFY2(opaqueFunc() > 2, QByteArray::number(opaqueFunc()).constData());
596 QTRY_VERIFY2_WITH_TIMEOUT(opaqueFunc() < 2, QByteArray::number(opaqueFunc()).constData(), 1);
597}
598
599void tst_Cmptest::verifyExplicitOperatorBool()
600{
601 struct ExplicitOperatorBool {
602 int m_i;
603 explicit ExplicitOperatorBool(int i) : m_i(i) {}
604 explicit operator bool() const { return m_i > 0; }
605 bool operator !() const { return !bool(*this); }
606 };
607
608 ExplicitOperatorBool val1(42);
609 QVERIFY(val1);
610
611 ExplicitOperatorBool val2(-273);
612 QVERIFY(!val2);
613}
614
615QTEST_MAIN(tst_Cmptest)
616#include "tst_cmptest.moc"
617

source code of qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp