1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
5** Copyright (C) 2016 Intel Corporation.
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the test suite of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:GPL-EXCEPT$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU
21** General Public License version 3 as published by the Free Software
22** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
23** included in the packaging of this file. Please review the following
24** information to ensure the GNU General Public License requirements will
25** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26**
27** $QT_END_LICENSE$
28**
29****************************************************************************/
30
31#include <QtTest/QtTest>
32
33#include <qvariant.h>
34#include <QtCore/private/qvariant_p.h>
35#include <qbitarray.h>
36#include <qbytearraylist.h>
37#include <qdatetime.h>
38#include <qmap.h>
39#include <qiodevice.h>
40#include <qurl.h>
41#include <qlocale.h>
42#include <qdebug.h>
43#include <qjsondocument.h>
44#include <quuid.h>
45
46#include <limits.h>
47#include <float.h>
48#include <cmath>
49#if __has_include(<variant>) && __cplusplus >= 201703L
50#include <variant>
51#endif
52#include <QLinkedList>
53#include <QRegularExpression>
54#include <QDir>
55#include <QBuffer>
56#include "qnumeric.h"
57
58#include <private/qlocale_p.h>
59#include "tst_qvariant_common.h"
60
61class CustomNonQObject;
62
63class tst_QVariant : public QObject
64{
65 Q_OBJECT
66
67public:
68 tst_QVariant(QObject *parent = 0)
69 : QObject(parent), customNonQObjectPointer(0)
70 {
71
72 }
73
74
75 enum MetaEnumTest_Enum0 { MetaEnumTest_Enum0_dummy = 2, MetaEnumTest_Enum0_value = 42, MetaEnsureSignedEnum0 = -1 };
76 Q_ENUM(MetaEnumTest_Enum0)
77 enum MetaEnumTest_Enum1 : qint64 { MetaEnumTest_Enum1_value = 42, MetaEnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
78 Q_ENUM(MetaEnumTest_Enum1)
79
80 enum MetaEnumTest_Enum3 : qint64 { MetaEnumTest_Enum3_value = -47, MetaEnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5, MetaEnumTest_Enum3_bigNegValue = -(Q_INT64_C(1) << 56) - 3 };
81 Q_ENUM(MetaEnumTest_Enum3)
82 enum MetaEnumTest_Enum4 : quint64 { MetaEnumTest_Enum4_value = 47, MetaEnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
83 Q_ENUM(MetaEnumTest_Enum4)
84 enum MetaEnumTest_Enum5 : uint { MetaEnumTest_Enum5_value = 47 };
85 Q_ENUM(MetaEnumTest_Enum5)
86 enum MetaEnumTest_Enum6 : uchar { MetaEnumTest_Enum6_value = 47 };
87 Q_ENUM(MetaEnumTest_Enum6)
88 enum MetaEnumTest_Enum8 : short { MetaEnumTest_Enum8_value = 47 };
89 Q_ENUM(MetaEnumTest_Enum8)
90
91private slots:
92 void cleanupTestCase();
93
94 void constructor();
95 void copy_constructor();
96 void constructor_invalid_data();
97 void constructor_invalid();
98 void isNull();
99 void swap();
100
101 void canConvert_data();
102 void canConvert();
103
104 void toSize_data();
105 void toSize();
106
107 void toSizeF_data();
108 void toSizeF();
109
110 void toPoint_data();
111 void toPoint();
112
113 void toRect_data();
114 void toRect();
115
116 void toChar_data();
117 void toChar();
118
119 void toLine_data();
120 void toLine();
121
122 void toLineF_data();
123 void toLineF();
124
125 void toInt_data();
126 void toInt();
127
128 void toUInt_data();
129 void toUInt();
130
131 void toBool_data();
132 void toBool();
133
134 void toLongLong_data();
135 void toLongLong();
136
137 void toULongLong_data();
138 void toULongLong();
139
140 void toByteArray_data();
141 void toByteArray();
142
143 void toString_data();
144 void toString();
145
146 void toDate_data();
147 void toDate();
148
149 void toTime_data();
150 void toTime();
151
152 void toDateTime_data();
153 void toDateTime();
154
155 void toDouble_data();
156 void toDouble();
157
158 void toFloat_data();
159 void toFloat();
160
161 void toPointF_data();
162 void toPointF();
163
164 void toRectF_data();
165 void toRectF();
166
167 void qvariant_cast_QObject_data();
168 void qvariant_cast_QObject();
169 void qvariant_cast_QObject_derived();
170 void qvariant_cast_QObject_wrapper();
171 void qvariant_cast_QSharedPointerQObject();
172
173 void toLocale();
174
175 void toRegExp();
176 void toRegularExpression();
177
178 void url();
179
180 void userType();
181 void basicUserType();
182
183 void variant_to();
184
185 void writeToReadFromDataStream_data();
186 void writeToReadFromDataStream();
187 void writeToReadFromOldDataStream();
188 void checkDataStream();
189
190 void operator_eq_eq_data();
191 void operator_eq_eq();
192 void operator_eq_eq_rhs();
193 void compareNumbers_data() const;
194 void compareNumbers() const;
195
196 void typeName_data();
197 void typeName();
198 void typeToName();
199
200 void streamInvalidVariant();
201
202 void podUserType();
203
204 void data();
205 void constData();
206
207 void saveLoadCustomTypes();
208
209 void variantMap();
210 void variantHash();
211
212 void convertToQUint8() const;
213 void comparePointers() const;
214 void voidStar() const;
215 void dataStar() const;
216 void canConvertQStringList() const;
217 void canConvertQStringList_data() const;
218 void canConvertMetaTypeToInt() const;
219 void variantToDateTimeWithoutWarnings() const;
220 void invalidDateTime() const;
221
222 void loadUnknownUserType();
223 void loadBrokenUserType();
224
225 void invalidDate() const;
226 void compareCustomTypes() const;
227 void timeToDateTime() const;
228 void copyingUserTypes() const;
229 void convertBoolToByteArray() const;
230 void convertBoolToByteArray_data() const;
231 void convertByteArrayToBool() const;
232 void convertByteArrayToBool_data() const;
233 void convertIterables() const;
234 void toIntFromQString() const;
235 void toIntFromDouble() const;
236 void setValue();
237 void fpStringRoundtrip_data() const;
238 void fpStringRoundtrip() const;
239
240 void numericalConvert_data();
241 void numericalConvert();
242 void moreCustomTypes();
243 void movabilityTest();
244 void variantInVariant();
245 void userConversion();
246 void modelIndexConversion();
247
248 void forwardDeclare();
249 void debugStream_data();
250 void debugStream();
251 void debugStreamType_data();
252 void debugStreamType();
253
254 void loadQt4Stream_data();
255 void loadQt4Stream();
256 void saveQt4Stream_data();
257 void saveQt4Stream();
258 void loadQt5Stream_data();
259 void loadQt5Stream();
260 void saveQt5Stream_data();
261 void saveQt5Stream();
262 void saveInvalid_data();
263 void saveInvalid();
264 void saveNewBuiltinWithOldStream();
265
266 void implicitConstruction();
267
268 void iterateContainerElements();
269 void pairElements();
270
271 void enums();
272 void metaEnums();
273 void compareSanity_data();
274 void compareSanity();
275 void compareRich();
276
277 void nullConvert();
278
279 void accessSequentialContainerKey();
280 void shouldDeleteVariantDataWorksForSequential();
281 void shouldDeleteVariantDataWorksForAssociative();
282 void fromStdVariant();
283 void qt4UuidDataStream();
284 void sequentialIterableEndianessSanityCheck();
285 void sequentialIterableAppend();
286
287 void preferDirectConversionOverInterfaces();
288
289private:
290 void dataStream_data(QDataStream::Version version);
291 void loadQVariantFromDataStream(QDataStream::Version version);
292 void saveQVariantFromDataStream(QDataStream::Version version);
293
294 CustomNonQObject *customNonQObjectPointer;
295 QVector<QObject*> objectPointerTestData;
296};
297
298const qlonglong intMax1 = (qlonglong)INT_MAX + 1;
299const qulonglong uintMax1 = (qulonglong)UINT_MAX + 1;
300
301void tst_QVariant::constructor()
302{
303 QVariant variant;
304 QVERIFY( !variant.isValid() );
305 QVERIFY( variant.isNull() );
306
307 QVariant var2(variant);
308 QVERIFY( !var2.isValid() );
309 QVERIFY( variant.isNull() );
310
311 QVariant varll(intMax1);
312 QVariant varll2(varll);
313 QCOMPARE(varll2, varll);
314
315 QVariant var3(QVariant::String);
316 QCOMPARE(var3.typeName(), "QString");
317 QVERIFY(var3.isNull());
318 QVERIFY(var3.isValid());
319
320 QVariant var4(QVariant::Invalid);
321 QCOMPARE(var4.type(), QVariant::Invalid);
322 QVERIFY(var4.isNull());
323 QVERIFY(!var4.isValid());
324
325 QVariant var5(QLatin1String("hallo"));
326 QCOMPARE(var5.type(), QVariant::String);
327 QCOMPARE(var5.typeName(), "QString");
328
329 QVariant var6(qlonglong(0));
330 QCOMPARE(var6.type(), QVariant::LongLong);
331 QCOMPARE(var6.typeName(), "qlonglong");
332
333 QVariant var7 = 5;
334 QVERIFY(var7.isValid());
335 QVERIFY(!var7.isNull());
336 QVariant var8;
337 var8.setValue<int>(5);
338 QVERIFY(var8.isValid());
339 QVERIFY(!var8.isNull());
340}
341
342void tst_QVariant::constructor_invalid_data()
343{
344 QTest::addColumn<uint>(name: "typeId");
345
346 QTest::newRow(dataTag: "-1") << uint(-1);
347 QTest::newRow(dataTag: "-122234567") << uint(-122234567);
348 QTest::newRow(dataTag: "0xfffffffff") << uint(0xfffffffff);
349 QTest::newRow(dataTag: "LastCoreType + 1") << uint(QMetaType::LastCoreType + 1);
350 QVERIFY(!QMetaType::isRegistered(QMetaType::LastCoreType + 1));
351}
352
353void tst_QVariant::constructor_invalid()
354{
355
356 QFETCH(uint, typeId);
357 {
358 QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression("^Trying to construct an instance of an invalid type, type id:"));
359 QVariant variant(static_cast<QVariant::Type>(typeId));
360 QVERIFY(!variant.isValid());
361 QCOMPARE(variant.userType(), int(QMetaType::UnknownType));
362 }
363 {
364 QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression("^Trying to construct an instance of an invalid type, type id:"));
365 QVariant variant(typeId, /* copy */ 0);
366 QVERIFY(!variant.isValid());
367 QCOMPARE(variant.userType(), int(QMetaType::UnknownType));
368 }
369}
370
371void tst_QVariant::copy_constructor()
372{
373 QVariant var7(QVariant::Int);
374 QVariant var8(var7);
375 QCOMPARE(var8.type(), QVariant::Int);
376 QVERIFY(var8.isNull());
377}
378
379Q_DECLARE_METATYPE(int*)
380
381void tst_QVariant::isNull()
382{
383 QVariant var;
384 QVERIFY( var.isNull() );
385
386 QString str1;
387 QVariant var1( str1 );
388 QVERIFY( var1.isNull() );
389#if QT_DEPRECATED_SINCE(5, 9)
390QT_WARNING_PUSH
391QT_WARNING_DISABLE_DEPRECATED
392 QVariant var2( QString::null );
393QT_WARNING_POP
394 QVERIFY( var2.isNull() );
395#endif
396
397 QVariant var3( QString( "blah" ) );
398 QVERIFY( !var3.isNull() );
399
400 QVariant var4( 0 );
401 QVERIFY( !var4.isNull() );
402
403 QVariant var5 = QString();
404 QVERIFY( var5.isNull() );
405
406 QVariant var6( QString( "blah" ) );
407 QVERIFY( !var6.isNull() );
408 var6 = QVariant();
409 QVERIFY( var6.isNull() );
410 var6.convert( targetTypeId: QVariant::String );
411 QVERIFY( var6.isNull() );
412 QVariant varLL( (qlonglong)0 );
413 QVERIFY( !varLL.isNull() );
414
415#if QT_DEPRECATED_SINCE(5, 9)
416QT_WARNING_PUSH
417QT_WARNING_DISABLE_DEPRECATED
418 QVariant var7(QString::null);
419QT_WARNING_POP
420 QVERIFY(var7.isNull());
421QT_WARNING_PUSH
422QT_WARNING_DISABLE_DEPRECATED
423 var7 = QVariant::fromValue<QString>(value: QString::null);
424QT_WARNING_POP
425 QVERIFY(var7.isNull());
426#endif
427
428 QVariant var8(QMetaType::Nullptr, nullptr);
429 QVERIFY(var8.isNull());
430 var8 = QVariant::fromValue<std::nullptr_t>(value: nullptr);
431 QVERIFY(var8.isNull());
432 QVariant var9 = QVariant(QJsonValue(QJsonValue::Null));
433 QVERIFY(var9.isNull());
434 var9 = QVariant::fromValue<QJsonValue>(value: QJsonValue(QJsonValue::Null));
435 QVERIFY(var9.isNull());
436
437 QVariant var10(QMetaType::VoidStar, nullptr);
438 QVERIFY(var10.isNull());
439 var10 = QVariant::fromValue<void*>(value: nullptr);
440 QVERIFY(var10.isNull());
441
442 QVariant var11(QMetaType::QObjectStar, nullptr);
443 QVERIFY(var11.isNull());
444 var11 = QVariant::fromValue<QObject*>(value: nullptr);
445 QVERIFY(var11.isNull());
446
447 QVERIFY(QVariant::fromValue<int*>(nullptr).isNull());
448
449 QVariant var12(QVariant::fromValue<QString>(value: QString()));
450 QVERIFY(var12.isNull());
451}
452
453void tst_QVariant::swap()
454{
455 QVariant v1 = 1, v2 = 2.0;
456 v1.swap(other&: v2);
457 QCOMPARE(v1.type(),QVariant::Double);
458 QCOMPARE(v1.toDouble(),2.0);
459 QCOMPARE(v2.type(),QVariant::Int);
460 QCOMPARE(v2.toInt(),1);
461}
462
463void tst_QVariant::canConvert_data()
464{
465 TST_QVARIANT_CANCONVERT_DATATABLE_HEADERS
466
467
468#ifdef Y
469#undef Y
470#endif
471#ifdef N
472#undef N
473#endif
474#define Y true
475#define N false
476 // bita bitm bool brsh byta col curs date dt dbl font img int inv kseq list ll map pal pen pix pnt rect reg size sp str strl time uint ull
477
478
479 QVariant var(QBitArray(0));
480 QTest::newRow(dataTag: "BitArray")
481 << var << Y << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N;
482 var = QVariant(QByteArray());
483 QTest::newRow(dataTag: "ByteArray")
484 << var << N << N << Y << N << Y << Y << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
485 var = QVariant(QDate());
486 QTest::newRow(dataTag: "Date")
487 << var << N << N << N << N << N << N << N << Y << Y << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N;
488 var = QVariant(QDateTime());
489 QTest::newRow(dataTag: "DateTime")
490 << var << N << N << N << N << N << N << N << Y << Y << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << Y << N << N;
491 var = QVariant((double)0.1);
492 QTest::newRow(dataTag: "Double")
493 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
494 var = QVariant(0.1f);
495 QTest::newRow(dataTag: "Float")
496 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
497 var = QVariant((int)1);
498 QTest::newRow(dataTag: "Int")
499 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
500 var = QVariant();
501 QTest::newRow(dataTag: "Invalid")
502 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N;
503 var = QVariant(QList<QVariant>());
504 QTest::newRow(dataTag: "List")
505 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N;
506 var = QVariant((qlonglong)1);
507 QTest::newRow(dataTag: "LongLong")
508 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
509 var = QVariant(QMap<QString,QVariant>());
510 QTest::newRow(dataTag: "Map")
511 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << N << N;
512 var = QVariant(QPoint());
513 QTest::newRow(dataTag: "Point")
514 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N;
515 var = QVariant(QRect());
516 QTest::newRow(dataTag: "Rect")
517 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N;
518 var = QVariant(QSize());
519 QTest::newRow(dataTag: "Size")
520 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N;
521 var = QVariant(QString());
522 QTest::newRow(dataTag: "String")
523 << var << N << N << Y << N << Y << Y << N << Y << Y << Y << Y << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << Y << Y << Y << Y;
524 var = QVariant(QStringList("entry"));
525 QTest::newRow(dataTag: "StringList")
526 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << Y << Y << N << N << N;
527 var = QVariant(QTime());
528 QTest::newRow(dataTag: "Time")
529 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << Y << N << N;
530 var = QVariant((uint)1);
531 QTest::newRow(dataTag: "UInt")
532 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
533 var = QVariant((int)1);
534 QTest::newRow(dataTag: "Int")
535 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
536 var = QVariant((qulonglong)1);
537 QTest::newRow(dataTag: "ULongLong")
538 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
539 var = QVariant::fromValue(value: 'a');
540 QTest::newRow(dataTag: "Char")
541 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
542 var = QVariant::fromValue<signed char>(value: -1);
543 QTest::newRow(dataTag: "SChar")
544 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
545 var = QVariant((short)-3);
546 QTest::newRow(dataTag: "Short")
547 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
548 var = QVariant((ushort)7);
549 QTest::newRow(dataTag: "UShort")
550 << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
551 var = QVariant::fromValue<QJsonValue>(value: QJsonValue(QStringLiteral("hello")));
552 QTest::newRow(dataTag: "JsonValue")
553 << var << N << N << Y << N << N << N << N << N << N << Y << N << N << Y << N << N << Y << Y << Y << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
554 var = QVariant::fromValue<QJsonArray>(value: QJsonArray());
555 QTest::newRow(dataTag: "JsonArray")
556 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N;
557 var = QVariant::fromValue<QJsonObject>(value: QJsonObject());
558 QTest::newRow(dataTag: "JsonObject")
559 << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << N << N;
560
561#undef N
562#undef Y
563}
564
565void tst_QVariant::canConvert()
566{
567 TST_QVARIANT_CANCONVERT_FETCH_DATA
568
569 TST_QVARIANT_CANCONVERT_COMPARE_DATA
570
571 // Invalid type ids
572 QCOMPARE(val.canConvert(-1), false);
573 QCOMPARE(val.canConvert(-23), false);
574 QCOMPARE(val.canConvert(-23876), false);
575 QCOMPARE(val.canConvert(23876), false);
576}
577
578void tst_QVariant::toInt_data()
579{
580 QTest::addColumn<QVariant>(name: "value");
581 QTest::addColumn<int>(name: "result");
582 QTest::addColumn<bool>(name: "valueOK");
583
584 QTest::newRow( dataTag: "invalid" ) << QVariant() << 0 << false;
585 QTest::newRow( dataTag: "int" ) << QVariant( 123 ) << 123 << true;
586 QTest::newRow( dataTag: "char" ) << QVariant::fromValue(value: 'a') << int('a') << true;
587 signed char signedChar = -13;
588 QTest::newRow( dataTag: "signed char" ) << QVariant::fromValue(value: signedChar) << -13 << true;
589 QTest::newRow( dataTag: "short" ) << QVariant::fromValue(value: short(-7)) << int(-7) << true;
590 QTest::newRow( dataTag: "ushort" ) << QVariant::fromValue(value: ushort(30000)) << 30000 << true;
591 QTest::newRow( dataTag: "double" ) << QVariant( 3.1415927 ) << 3 << true;
592 QTest::newRow( dataTag: "float" ) << QVariant( 3.1415927f ) << 3 << true;
593 QTest::newRow( dataTag: "uint" ) << QVariant( 123u ) << 123 << true;
594 QTest::newRow( dataTag: "int-string" ) << QVariant( QString("123") ) << 123 << true;
595 QTest::newRow( dataTag: "string" ) << QVariant( QString("Unicode String") ) << 0 << false;
596 QTest::newRow( dataTag: "longlong0" ) << QVariant( (qlonglong)34 ) << 34 << true;
597 QTest::newRow( dataTag: "longlong1" ) << QVariant( intMax1 ) << (int)INT_MIN << true;
598 QTest::newRow( dataTag: "ulonglong0" ) << QVariant( (qulonglong)34 ) << 34 << true;
599 QTest::newRow( dataTag: "ulonglong1" ) << QVariant( uintMax1 ) << 0 << true;
600 QTest::newRow( dataTag: "signedint" ) << QVariant( -123 ) << -123 << true;
601 QTest::newRow( dataTag: "signeddouble" ) << QVariant( -3.1415927 ) << -3 << true;
602 QTest::newRow( dataTag: "signedfloat" ) << QVariant( -3.1415927f ) << -3 << true;
603 QTest::newRow( dataTag: "signedint-string" ) << QVariant( QString("-123") ) << -123 << true;
604 QTest::newRow( dataTag: "signedlonglong0" ) << QVariant( (qlonglong)-34 ) << -34 << true;
605 QTest::newRow( dataTag: "QChar" ) << QVariant(QChar('a')) << int('a') << true;
606 QByteArray bytearray(4, ' ');
607 bytearray[0] = 'T';
608 bytearray[1] = 'e';
609 bytearray[2] = 's';
610 bytearray[3] = 't';
611 QTest::newRow( dataTag: "QByteArray1" ) << QVariant( bytearray ) << 0 << false;
612 bytearray[0] = '4';
613 bytearray[1] = '5';
614 bytearray[2] = '0';
615 bytearray[3] = '0';
616 QTest::newRow( dataTag: "QByteArray2" ) << QVariant( bytearray ) << 4500 << true;
617 QTest::newRow(dataTag: "int-QJsonValue") << QVariant(QJsonValue(321)) << 321 << true;
618 QTest::newRow(dataTag: "undefined-QJsonValue") << QVariant(QJsonValue(QJsonValue::Undefined)) << 0 << false;
619}
620
621void tst_QVariant::toInt()
622{
623 QFETCH( QVariant, value );
624 QFETCH( int, result );
625 QFETCH( bool, valueOK );
626 QVERIFY( value.isValid() == value.canConvert( QVariant::Int ) );
627 bool ok;
628 int i = value.toInt( ok: &ok );
629 QCOMPARE( i, result );
630 QVERIFY( ok == valueOK );
631}
632
633void tst_QVariant::toUInt_data()
634{
635 QTest::addColumn<QVariant>(name: "value");
636 QTest::addColumn<uint>(name: "result");
637 QTest::addColumn<bool>(name: "valueOK");
638
639 QTest::newRow( dataTag: "int" ) << QVariant( 123 ) << (uint)123 << true;
640 QTest::newRow( dataTag: "char" ) << QVariant::fromValue(value: 'a') << uint('a') << true;
641 signed char signedChar = 12;
642 QTest::newRow( dataTag: "signed char" ) << QVariant::fromValue(value: signedChar) << uint(12) << true;
643 QTest::newRow( dataTag: "double" ) << QVariant( 3.1415927 ) << (uint)3 << true;
644 QTest::newRow( dataTag: "float" ) << QVariant( 3.1415927f ) << (uint)3 << true;
645 QTest::newRow( dataTag: "uint" ) << QVariant( 123u ) << (uint)123 << true;
646 QTest::newRow( dataTag: "int-string" ) << QVariant( QString("123") ) << (uint)123 << true;
647 QTest::newRow( dataTag: "string" ) << QVariant( QString("Unicode String") ) << (uint)0 << false;
648 QTest::newRow( dataTag: "string2" ) << QVariant( QString("4") ) << (uint)4 << true;
649 QTest::newRow( dataTag: "longlong0" ) << QVariant( (qlonglong)34 ) << (uint)34 << true;
650 QTest::newRow( dataTag: "longlong1" ) << QVariant( intMax1 ) << (uint)INT_MIN << true;
651 QTest::newRow( dataTag: "ulonglong0" ) << QVariant( (qulonglong)34 ) << (uint)34 << true;
652 QTest::newRow( dataTag: "ulonglong1" ) << QVariant( uintMax1 ) << (uint)0 << true;
653 QTest::newRow( dataTag: "negativeint" ) << QVariant( -123 ) << (uint)-123 << true;
654 QTest::newRow( dataTag: "negativedouble" ) << QVariant( -3.1415927 ) << (uint)-3 << true;
655 QTest::newRow( dataTag: "negativefloat" ) << QVariant( -3.1415927f ) << (uint)-3 << true;
656 QTest::newRow( dataTag: "negativeint-string" ) << QVariant( QString("-123") ) << (uint)0 << false;
657 QTest::newRow( dataTag: "negativelonglong0" ) << QVariant( (qlonglong)-34 ) << (uint)-34 << true;
658 QTest::newRow( dataTag: "QChar" ) << QVariant(QChar('a')) << uint('a') << true;
659 QByteArray bytearray(4, ' ');
660 bytearray[0] = '4';
661 bytearray[1] = '3';
662 bytearray[2] = '2';
663 bytearray[3] = '1';
664 QTest::newRow( dataTag: "QByteArray" ) << QVariant( bytearray ) << (uint)4321 << true;
665 QTest::newRow(dataTag: "int-QJsonValue") << QVariant(QJsonValue(321)) << (uint)321 << true;
666 QTest::newRow(dataTag: "null-QJsonValue") << QVariant(QJsonValue(QJsonValue::Null)) << (uint)0 << false;
667}
668
669void tst_QVariant::toUInt()
670{
671 QFETCH( QVariant, value );
672 QFETCH( uint, result );
673 QFETCH( bool, valueOK );
674 QVERIFY( value.isValid() );
675 QVERIFY( value.canConvert( QVariant::UInt ) );
676
677 bool ok;
678 uint i = value.toUInt( ok: &ok );
679 QVERIFY( ok == valueOK );
680 QCOMPARE( i, result );
681}
682
683
684void tst_QVariant::toSize_data()
685{
686 QTest::addColumn<QVariant>(name: "value");
687 QTest::addColumn<QSize>(name: "result");
688 QTest::newRow( dataTag: "qsizef4" ) << QVariant( QSizeF(4, 2) ) << QSize(4, 2);
689 QTest::newRow( dataTag: "qsizef1" ) << QVariant( QSizeF(0, 0) ) << QSize(0, 0);
690 QTest::newRow( dataTag: "qsizef2" ) << QVariant( QSizeF(-5, -1) ) << QSize(-5, -1);
691 QTest::newRow( dataTag: "qsizef3" ) << QVariant( QSizeF() ) << QSize();
692}
693
694void tst_QVariant::toSize()
695{
696 QFETCH( QVariant, value );
697 QFETCH( QSize, result );
698 QVERIFY( value.isValid() );
699 QVERIFY( value.canConvert( QVariant::Size ) );
700
701 QSize i = value.toSize();
702 QCOMPARE( i, result );
703}
704
705void tst_QVariant::toSizeF_data()
706{
707 QTest::addColumn<QVariant>(name: "value");
708 QTest::addColumn<QSizeF>(name: "result");
709 QTest::newRow( dataTag: "qsize1" ) << QVariant( QSize(0, 0) ) << QSizeF(0, 0);
710 QTest::newRow( dataTag: "qsize2" ) << QVariant( QSize(-5, -1) ) << QSizeF(-5, -1);
711 QTest::newRow( dataTag: "qsize3" ) << QVariant( QSize() ) << QSizeF();
712 QTest::newRow( dataTag: "qsize4" ) << QVariant(QSize(4,2)) << QSizeF(4,2);
713}
714
715void tst_QVariant::toSizeF()
716{
717 QFETCH( QVariant, value );
718 QFETCH( QSizeF, result );
719 QVERIFY( value.isValid() );
720 QVERIFY( value.canConvert( QVariant::SizeF ) );
721
722 QSizeF i = value.toSizeF();
723 QCOMPARE( i, result );
724}
725
726void tst_QVariant::toLine_data()
727{
728 QTest::addColumn<QVariant>(name: "value");
729 QTest::addColumn<QLine>(name: "result");
730 QTest::newRow( dataTag: "linef1" ) << QVariant( QLineF(1, 2, 3, 4) ) << QLine(1, 2, 3, 4);
731 QTest::newRow( dataTag: "linef2" ) << QVariant( QLineF(-1, -2, -3, -4) ) << QLine(-1, -2, -3, -4);
732 QTest::newRow( dataTag: "linef3" ) << QVariant( QLineF(0, 0, 0, 0) ) << QLine(0, 0, 0, 0);
733 QTest::newRow( dataTag: "linef4" ) << QVariant( QLineF() ) << QLine();
734}
735
736void tst_QVariant::toLine()
737{
738 QFETCH( QVariant, value );
739 QFETCH( QLine, result );
740 QVERIFY( value.isValid() );
741 QVERIFY( value.canConvert( QVariant::Line ) );
742
743 QLine i = value.toLine();
744 QCOMPARE( i, result );
745}
746
747void tst_QVariant::toLineF_data()
748{
749 QTest::addColumn<QVariant>(name: "value");
750 QTest::addColumn<QLineF>(name: "result");
751 QTest::newRow( dataTag: "line1" ) << QVariant( QLine(-1, -2, -3, -4) ) << QLineF(-1, -2, -3, -4);
752 QTest::newRow( dataTag: "line2" ) << QVariant( QLine(0, 0, 0, 0) ) << QLineF(0, 0, 0, 0);
753 QTest::newRow( dataTag: "line3" ) << QVariant( QLine() ) << QLineF();
754 QTest::newRow( dataTag: "line4" ) << QVariant( QLine(1, 2, 3, 4) ) << QLineF(1, 2, 3, 4);
755}
756
757void tst_QVariant::toLineF()
758{
759 QFETCH( QVariant, value );
760 QFETCH( QLineF, result );
761 QVERIFY( value.isValid() );
762 QVERIFY( value.canConvert( QVariant::LineF ) );
763
764 QLineF i = value.toLineF();
765 QCOMPARE( i, result );
766}
767
768void tst_QVariant::toPoint_data()
769{
770 QTest::addColumn<QVariant>(name: "value");
771 QTest::addColumn<QPoint>(name: "result");
772 QTest::newRow( dataTag: "pointf1" ) << QVariant( QPointF(4, 2) ) << QPoint(4, 2);
773 QTest::newRow( dataTag: "pointf2" ) << QVariant( QPointF(0, 0) ) << QPoint(0, 0);
774 QTest::newRow( dataTag: "pointf3" ) << QVariant( QPointF(-4, -2) ) << QPoint(-4, -2);
775 QTest::newRow( dataTag: "pointf4" ) << QVariant( QPointF() ) << QPoint();
776 QTest::newRow( dataTag: "pointf5" ) << QVariant( QPointF(-4.2f, -2.3f) ) << QPoint(-4, -2);
777}
778
779void tst_QVariant::toPoint()
780{
781 QFETCH( QVariant, value );
782 QFETCH( QPoint, result );
783 QVERIFY( value.isValid() );
784 QVERIFY( value.canConvert( QVariant::Point ) );
785 QPoint i = value.toPoint();
786 QCOMPARE( i, result );
787}
788
789void tst_QVariant::toRect_data()
790{
791 QTest::addColumn<QVariant>(name: "value");
792 QTest::addColumn<QRect>(name: "result");
793 QTest::newRow( dataTag: "rectf1" ) << QVariant(QRectF(1, 2, 3, 4)) << QRect(1, 2, 3, 4);
794 QTest::newRow( dataTag: "rectf2" ) << QVariant(QRectF(0, 0, 0, 0)) << QRect(0, 0, 0, 0);
795 QTest::newRow( dataTag: "rectf3" ) << QVariant(QRectF(-1, -2, -3, -4)) << QRect(-1, -2, -3, -4);
796 QTest::newRow( dataTag: "rectf4" ) << QVariant(QRectF(-1.3f, 0, 3.9f, -4.0)) << QRect(-1, 0, 4, -4);
797 QTest::newRow( dataTag: "rectf5" ) << QVariant(QRectF()) << QRect();
798}
799
800void tst_QVariant::toRect()
801{
802 QFETCH( QVariant, value );
803 QFETCH( QRect, result );
804 QVERIFY( value.isValid() );
805 QVERIFY( value.canConvert( QVariant::Rect ) );
806 QRect i = value.toRect();
807 QCOMPARE( i, result );
808}
809
810void tst_QVariant::toChar_data()
811{
812 QTest::addColumn<QVariant>(name: "value");
813 QTest::addColumn<QChar>(name: "result");
814 QTest::newRow( dataTag: "longlong" ) << QVariant(qlonglong('6')) << QChar('6');
815 QTest::newRow( dataTag: "ulonglong" ) << QVariant(qulonglong('7')) << QChar('7');
816}
817
818void tst_QVariant::toChar()
819{
820 QFETCH( QVariant, value );
821 QFETCH( QChar, result );
822 QVERIFY( value.isValid() );
823 QVERIFY( value.canConvert( QVariant::Char ) );
824
825 QChar i = value.toChar();
826 QCOMPARE( i, result );
827}
828
829void tst_QVariant::toBool_data()
830{
831 QTest::addColumn<QVariant>(name: "value");
832 QTest::addColumn<bool>(name: "result");
833
834 QTest::newRow( dataTag: "int0" ) << QVariant( 0 ) << false;
835 QTest::newRow( dataTag: "int1" ) << QVariant( 123 ) << true;
836 QTest::newRow( dataTag: "uint0" ) << QVariant( 0u ) << false;
837 QTest::newRow( dataTag: "uint1" ) << QVariant( 123u ) << true;
838 QTest::newRow( dataTag: "double0" ) << QVariant( 0.0 ) << false;
839 QTest::newRow( dataTag: "float0" ) << QVariant( 0.0f ) << false;
840 QTest::newRow( dataTag: "double1" ) << QVariant( 3.1415927 ) << true;
841 QTest::newRow( dataTag: "float1" ) << QVariant( 3.1415927f ) << true;
842 QTest::newRow( dataTag: "string0" ) << QVariant( QString("3") ) << true;
843 QTest::newRow( dataTag: "string1" ) << QVariant( QString("true") ) << true;
844 QTest::newRow( dataTag: "string2" ) << QVariant( QString("0") ) << false;
845 QTest::newRow( dataTag: "string3" ) << QVariant( QString("fAlSe") ) << false;
846 QTest::newRow( dataTag: "longlong0" ) << QVariant( (qlonglong)0 ) << false;
847 QTest::newRow( dataTag: "longlong1" ) << QVariant( (qlonglong)1 ) << true;
848 QTest::newRow( dataTag: "ulonglong0" ) << QVariant( (qulonglong)0 ) << false;
849 QTest::newRow( dataTag: "ulonglong1" ) << QVariant( (qulonglong)1 ) << true;
850 QTest::newRow( dataTag: "QChar" ) << QVariant(QChar('a')) << true;
851 QTest::newRow( dataTag: "Null_QChar" ) << QVariant(QChar(0)) << false;
852 QTest::newRow(dataTag: "QJsonValue(true)") << QVariant(QJsonValue(true)) << true;
853 QTest::newRow(dataTag: "QJsonValue(false)") << QVariant(QJsonValue(false)) << false;
854}
855
856void tst_QVariant::toBool()
857{
858 QFETCH( QVariant, value );
859 QFETCH( bool, result );
860 QVERIFY( value.isValid() );
861 QVERIFY( value.canConvert( QVariant::Bool ) );
862
863 bool i = value.toBool();
864 QCOMPARE( i, result );
865}
866
867void tst_QVariant::toPointF_data()
868{
869 QTest::addColumn<QVariant>(name: "value");
870 QTest::addColumn<QPointF>(name: "result");
871
872 QTest::newRow( dataTag: "QPoint" ) << QVariant( QPointF( 19, 84) ) << QPointF( 19, 84 );
873}
874
875void tst_QVariant::toPointF()
876{
877 QFETCH( QVariant, value );
878 QFETCH( QPointF, result );
879 QVERIFY( value.isValid() );
880 QVERIFY( value.canConvert( QVariant::PointF ) );
881 QPointF d = value.toPointF();
882 QCOMPARE( d, result );
883}
884
885void tst_QVariant::toRectF_data()
886{
887 QTest::addColumn<QVariant>(name: "value");
888 QTest::addColumn<QRectF>(name: "result");
889
890 QRect r( 1, 9, 8, 4 );
891 QRectF rf( 1.0, 9.0, 8.0, 4.0 );
892 QTest::newRow( dataTag: "QRect" ) << QVariant( r ) << rf;
893}
894
895void tst_QVariant::toRectF()
896{
897 QFETCH( QVariant, value );
898 QFETCH( QRectF, result );
899 QVERIFY( value.isValid() );
900 QVERIFY( value.canConvert( QVariant::RectF ) );
901 QRectF d = value.toRectF();
902 QCOMPARE( d, result );
903}
904
905void tst_QVariant::toDouble_data()
906{
907 QTest::addColumn<QVariant>(name: "value");
908 QTest::addColumn<double>(name: "result");
909 QTest::addColumn<bool>(name: "valueOK");
910
911 QByteArray bytearray(4, ' ');
912 bytearray[0] = '3';
913 bytearray[1] = '2';
914 bytearray[2] = '.';
915 bytearray[3] = '1';
916 QTest::newRow( dataTag: "bytearray" ) << QVariant( bytearray ) << 32.1 << true;
917 QTest::newRow(dataTag: "double-QJsonValue") << QVariant(QJsonValue(32.1)) << 32.1 << true;
918 QTest::newRow(dataTag: "null-QJsonValue") << QVariant(QJsonValue(QJsonValue::Null)) << 0.0 << false;
919}
920
921void tst_QVariant::toDouble()
922{
923 QFETCH( QVariant, value );
924 QFETCH( double, result );
925 QFETCH( bool, valueOK );
926 QVERIFY( value.isValid() );
927 QVERIFY( value.canConvert( QVariant::Double ) );
928 bool ok;
929 double d = value.toDouble( ok: &ok );
930 QCOMPARE( d, result );
931 QVERIFY( ok == valueOK );
932}
933
934void tst_QVariant::toFloat_data()
935{
936 QTest::addColumn<QVariant>(name: "value");
937 QTest::addColumn<float>(name: "result");
938 QTest::addColumn<bool>(name: "valueOK");
939
940 QByteArray bytearray(4, ' ');
941 bytearray[0] = '3';
942 bytearray[1] = '2';
943 bytearray[2] = '.';
944 bytearray[3] = '1';
945 QTest::newRow(dataTag: "QByteArray") << QVariant(bytearray) << float(32.1) << true;
946 QTest::newRow(dataTag: "double-QJsonValue") << QVariant(QJsonValue(32.1)) << float(32.1) << true;
947 QTest::newRow(dataTag: "undefined-QJsonValue") << QVariant(QJsonValue(QJsonValue::Undefined)) << float(0.0) << false;
948}
949
950void tst_QVariant::toFloat()
951{
952 QFETCH(QVariant, value );
953 QFETCH(float, result);
954 QFETCH(bool, valueOK);
955 QVERIFY(value.isValid());
956 QVERIFY(value.canConvert(QMetaType::Float));
957 bool ok;
958 float d = value.toFloat(ok: &ok);
959 QCOMPARE(d, result);
960 QCOMPARE(ok, valueOK);
961}
962
963void tst_QVariant::toLongLong_data()
964{
965 QTest::addColumn<QVariant>(name: "value");
966 QTest::addColumn<qlonglong>(name: "result");
967 QTest::addColumn<bool>(name: "valueOK");
968
969 QTest::newRow( dataTag: "int0" ) << QVariant( 123 ) << (qlonglong)123 << true;
970 QTest::newRow( dataTag: "double" ) << QVariant( 3.1415927 ) << (qlonglong)3 << true;
971 QTest::newRow( dataTag: "float" ) << QVariant( 3.1415927f ) << (qlonglong)3 << true;
972 QTest::newRow( dataTag: "uint" ) << QVariant( 123u ) << (qlonglong)123 << true;
973 QTest::newRow( dataTag: "int-string" ) << QVariant( QString("123") )
974 << (qlonglong)123 << true;
975 QTest::newRow( dataTag: "string" ) << QVariant( QString("Unicode fun") ) << (qlonglong)0
976 << false;
977 QTest::newRow( dataTag: "longlong" ) << QVariant( intMax1 ) << intMax1 << true;
978 QTest::newRow( dataTag: "ulonglong" ) << QVariant( uintMax1 ) << (qlonglong)uintMax1 << true;
979 QTest::newRow( dataTag: "QChar" ) << QVariant(QChar('a')) << qlonglong('a') << true;
980 QByteArray bytearray(4, ' ');
981 bytearray[0] = '3';
982 bytearray[1] = '2';
983 bytearray[2] = '0';
984 bytearray[3] = '0';
985 QTest::newRow( dataTag: "QByteArray" ) << QVariant( bytearray ) << (qlonglong) 3200 << true;
986 QTest::newRow(dataTag: "int-QJsonValue") << QVariant(QJsonValue(321)) << (qlonglong)321 << true;
987 QTest::newRow(dataTag: "string-QJsonValue") << QVariant(QJsonValue(QString("string"))) << (qlonglong)0 << false;
988
989 qint64 value64 = (Q_INT64_C(12) << 35) + 8;
990 QTest::newRow(dataTag: "qint64") << QVariant::fromValue(value: value64) << qlonglong(value64) << true;
991 QTest::newRow(dataTag: "-qint64") << QVariant::fromValue(value: -value64) << qlonglong(-value64) << true;
992 QTest::newRow(dataTag: "long") << QVariant::fromValue(value: long(464646)) << qlonglong(464646) << true;
993 QTest::newRow(dataTag: "LONG_MAX") << QVariant::fromValue( LONG_MAX ) << qlonglong(LONG_MAX) << true;
994 QTest::newRow(dataTag: "LONG_MIN") << QVariant::fromValue( LONG_MIN ) << qlonglong(LONG_MIN) << true;
995
996 QTest::newRow( dataTag: "short" ) << QVariant(short(12)) << qlonglong(12) << true;
997 QTest::newRow( dataTag: "-short" ) << QVariant(short(-24)) << qlonglong(-24) << true;
998 QTest::newRow( dataTag: "ushort" ) << QVariant(ushort(15)) << qlonglong(15) << true;
999}
1000
1001void tst_QVariant::toLongLong()
1002{
1003 QFETCH( QVariant, value );
1004 QFETCH( qlonglong, result );
1005 QFETCH( bool, valueOK );
1006 QVERIFY( value.isValid() );
1007 QVERIFY( value.canConvert( QVariant::LongLong ) );
1008 bool ok;
1009 qlonglong ll = value.toLongLong( ok: &ok );
1010 QCOMPARE( ll, result );
1011 QVERIFY( ok == valueOK );
1012}
1013
1014void tst_QVariant::toULongLong_data()
1015{
1016 QTest::addColumn<QVariant>(name: "value");
1017 QTest::addColumn<qulonglong>(name: "result");
1018 QTest::addColumn<bool>(name: "valueOK");
1019
1020 QTest::newRow( dataTag: "int0" ) << QVariant( 123 ) << (qulonglong)123 << true;
1021 QTest::newRow( dataTag: "double" ) << QVariant( 3.1415927 ) << (qulonglong)3 << true;
1022 QTest::newRow( dataTag: "float" ) << QVariant( 3.1415927f ) << (qulonglong)3 << true;
1023 QTest::newRow( dataTag: "uint" ) << QVariant( 123u ) << (qulonglong)123 << true;
1024 QTest::newRow( dataTag: "int-string" ) << QVariant( QString("123") )
1025 << (qulonglong)123 << true;
1026 QTest::newRow( dataTag: "string" ) << QVariant( QString("Unicode fun") ) << (qulonglong)0
1027 << false;
1028 QTest::newRow( dataTag: "ulonglong-string" ) << QVariant( QString("18446744073709551615") )
1029 << Q_UINT64_C(18446744073709551615)
1030 << true;
1031 QTest::newRow( dataTag: "bytaa-string" ) << QVariant( QString("18446744073709551615") )
1032 << Q_UINT64_C(18446744073709551615)
1033 << true;
1034 QTest::newRow( dataTag: "longlong" ) << QVariant( intMax1 ) << (qulonglong)intMax1 << true;
1035 QTest::newRow( dataTag: "ulonglong" ) << QVariant( uintMax1 ) << uintMax1 << true;
1036 QTest::newRow( dataTag: "QChar" ) << QVariant(QChar('a')) << qulonglong('a') << true;
1037 QByteArray bytearray(4, ' ');
1038 bytearray[0] = '3';
1039 bytearray[1] = '2';
1040 bytearray[2] = '0';
1041 bytearray[3] = '1';
1042 QTest::newRow( dataTag: "QByteArray" ) << QVariant( bytearray ) << (qulonglong) 3201 << true;
1043 QTest::newRow(dataTag: "int-QJsonValue") << QVariant(QJsonValue(321)) << (qulonglong)321 << true;
1044 QTest::newRow(dataTag: "bool-QJsonValue") << QVariant(QJsonValue(true)) << (qulonglong)0 << false;
1045
1046 quint64 value64 = (Q_INT64_C(12) << 35) + 8;
1047 QTest::newRow(dataTag: "qint64") << QVariant::fromValue(value: value64) << qulonglong(value64) << true;
1048 QTest::newRow(dataTag: "long") << QVariant::fromValue(value: long(464646)) << qulonglong(464646) << true;
1049 QTest::newRow(dataTag: "LONG_MAX") << QVariant::fromValue( LONG_MAX ) << qulonglong(LONG_MAX) << true;
1050 QTest::newRow(dataTag: "ULONG_MAX") << QVariant::fromValue( ULONG_MAX ) << qulonglong(ULONG_MAX) << true;
1051 QTest::newRow( dataTag: "short" ) << QVariant(short(12)) << qulonglong(12) << true;
1052 QTest::newRow( dataTag: "-short" ) << QVariant(short(-24)) << qulonglong(-24) << true;
1053 QTest::newRow( dataTag: "ushort" ) << QVariant(ushort(15)) << qulonglong(15) << true;
1054}
1055
1056void tst_QVariant::toULongLong()
1057{
1058 QFETCH( QVariant, value );
1059 QFETCH( qulonglong, result );
1060 QFETCH( bool, valueOK );
1061 QVERIFY( value.isValid() );
1062 QVERIFY( value.canConvert( QVariant::ULongLong ) );
1063 bool ok;
1064 qulonglong ll = value.toULongLong( ok: &ok );
1065 QCOMPARE( ll, result );
1066 QVERIFY( ok == valueOK );
1067}
1068
1069void tst_QVariant::toByteArray_data()
1070{
1071 QTest::addColumn<QVariant>(name: "value");
1072 QTest::addColumn<QByteArray>(name: "result");
1073
1074 QByteArray ba(5, ' ');
1075 ba[0] = 'T';
1076 ba[1] = 'e';
1077 ba[2] = 's';
1078 ba[3] = 't';
1079 ba[4] = '\0';
1080
1081 QByteArray variantBa = ba;
1082
1083 QTest::newRow( dataTag: "qbytearray" ) << QVariant( variantBa ) << ba;
1084 QTest::newRow( dataTag: "int" ) << QVariant( -123 ) << QByteArray( "-123" );
1085 QTest::newRow( dataTag: "uint" ) << QVariant( (uint)123 ) << QByteArray( "123" );
1086 QTest::newRow( dataTag: "double" ) << QVariant( 123.456 ) << QByteArray( "123.456" );
1087
1088 // Conversion from float to double adds bits of which the double-to-string converter doesn't
1089 // know they're insignificant
1090 QTest::newRow( dataTag: "float" ) << QVariant( 123.456f ) << QByteArray( "123.45600128173828" );
1091
1092 QTest::newRow( dataTag: "longlong" ) << QVariant( (qlonglong)34 ) << QByteArray( "34" );
1093 QTest::newRow( dataTag: "ulonglong" ) << QVariant( (qulonglong)34 ) << QByteArray( "34" );
1094 QTest::newRow( dataTag: "nullptr" ) << QVariant::fromValue(value: nullptr) << QByteArray();
1095}
1096
1097void tst_QVariant::toByteArray()
1098{
1099 QFETCH( QVariant, value );
1100 QFETCH( QByteArray, result );
1101 QVERIFY( value.isValid() );
1102 QVERIFY( value.canConvert( QVariant::ByteArray ) );
1103 QByteArray ba = value.toByteArray();
1104 QCOMPARE( ba.isNull(), result.isNull() );
1105 QCOMPARE( ba, result );
1106
1107 QVERIFY( value.convert( QVariant::ByteArray ) );
1108 QCOMPARE( value.isNull(), result.isNull() );
1109 QCOMPARE( value.toByteArray().isNull(), result.isNull() );
1110 QCOMPARE( value.toByteArray(), result );
1111}
1112
1113void tst_QVariant::toString_data()
1114{
1115 QTest::addColumn<QVariant>(name: "value");
1116 QTest::addColumn<QString>(name: "result");
1117
1118 QTest::newRow( dataTag: "qstring" ) << QVariant( QString( "Test" ) ) << QString( "Test" );
1119 QTest::newRow( dataTag: "charstar" ) << QVariant(QLatin1String("Test")) << QString("Test");
1120 QTest::newRow( dataTag: "qbytearray") << QVariant( QByteArray( "Test\0" ) ) << QString( "Test" );
1121 QTest::newRow( dataTag: "int" ) << QVariant( -123 ) << QString( "-123" );
1122 QTest::newRow( dataTag: "uint" ) << QVariant( (uint)123 ) << QString( "123" );
1123 QTest::newRow( dataTag: "double" ) << QVariant( 123.456 ) << QString( "123.456" );
1124
1125 // Conversion from float to double adds bits of which the double-to-string converter doesn't
1126 // know they're insignificant
1127 QTest::newRow( dataTag: "float" ) << QVariant( 123.456f ) << QString( "123.45600128173828" );
1128
1129 QTest::newRow( dataTag: "bool" ) << QVariant( true ) << QString( "true" );
1130 QTest::newRow( dataTag: "qdate" ) << QVariant( QDate( 2002, 1, 1 ) ) << QString( "2002-01-01" );
1131 QTest::newRow( dataTag: "qtime" ) << QVariant( QTime( 12, 34, 56 ) ) << QString( "12:34:56.000" );
1132 QTest::newRow( dataTag: "qtime-with-ms" ) << QVariant( QTime( 12, 34, 56, 789 ) ) << QString( "12:34:56.789" );
1133 QTest::newRow( dataTag: "qdatetime" ) << QVariant( QDateTime( QDate( 2002, 1, 1 ), QTime( 12, 34, 56, 789 ) ) ) << QString( "2002-01-01T12:34:56.789" );
1134 QTest::newRow( dataTag: "llong" ) << QVariant( (qlonglong)Q_INT64_C(123456789012) ) <<
1135 QString( "123456789012" );
1136 QTest::newRow(dataTag: "QJsonValue") << QVariant(QJsonValue(QString("hello"))) << QString("hello");
1137 QTest::newRow(dataTag: "QJsonValue(Null)") << QVariant(QJsonValue(QJsonValue::Null)) << QString();
1138 QTest::newRow(dataTag: "nullptr") << QVariant::fromValue(value: nullptr) << QString();
1139}
1140
1141void tst_QVariant::toString()
1142{
1143 QFETCH( QVariant, value );
1144 QFETCH( QString, result );
1145 QVERIFY( value.isValid() );
1146 QVERIFY( value.canConvert( QVariant::String ) );
1147 QString str = value.toString();
1148 QCOMPARE( str.isNull(), result.isNull() );
1149 QCOMPARE( str, result );
1150
1151 QVERIFY( value.convert( QVariant::String ) );
1152 QCOMPARE( value.isNull(), result.isNull() );
1153 QCOMPARE( value.toString().isNull(), result.isNull() );
1154 QCOMPARE( value.toString(), result );
1155}
1156
1157void tst_QVariant::toDate_data()
1158{
1159 QTest::addColumn<QVariant>(name: "value");
1160 QTest::addColumn<QDate>(name: "result");
1161
1162 QTest::newRow( dataTag: "qdate" ) << QVariant( QDate( 2002, 10, 10 ) ) << QDate( 2002, 10, 10 );
1163 QTest::newRow( dataTag: "qdatetime" ) << QVariant( QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56 ) ) ) << QDate( 2002, 10, 10 );
1164 QTest::newRow( dataTag: "qstring" ) << QVariant( QString( "2002-10-10" ) ) << QDate( 2002, 10, 10 );
1165}
1166
1167void tst_QVariant::toDate()
1168{
1169 QFETCH( QVariant, value );
1170 QFETCH( QDate, result );
1171 QVERIFY( value.isValid() );
1172 QVERIFY( value.canConvert( QVariant::Date ) );
1173 QCOMPARE( value.toDate(), result );
1174}
1175
1176void tst_QVariant::toTime_data()
1177{
1178 QTest::addColumn<QVariant>(name: "value");
1179 QTest::addColumn<QTime>(name: "result");
1180
1181 QTest::newRow( dataTag: "qtime" ) << QVariant( QTime( 12, 34, 56 ) ) << QTime( 12, 34, 56 );
1182 QTest::newRow( dataTag: "qdatetime" ) << QVariant( QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56 ) ) ) << QTime( 12, 34, 56 );
1183 QTest::newRow( dataTag: "qstring" ) << QVariant( QString( "12:34:56" ) ) << QTime( 12, 34, 56 );
1184 QTest::newRow( dataTag: "qstring-with-ms" ) << QVariant( QString( "12:34:56.789" ) ) << QTime( 12, 34, 56, 789 );
1185}
1186
1187void tst_QVariant::toTime()
1188{
1189 QFETCH( QVariant, value );
1190 QFETCH( QTime, result );
1191 QVERIFY( value.isValid() );
1192 QVERIFY( value.canConvert( QVariant::Time ) );
1193 QCOMPARE( value.toTime(), result );
1194}
1195
1196void tst_QVariant::toDateTime_data()
1197{
1198 QTest::addColumn<QVariant>(name: "value");
1199 QTest::addColumn<QDateTime>(name: "result");
1200
1201 QTest::newRow( dataTag: "qdatetime" ) << QVariant( QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56 ) ) )
1202 << QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56 ) );
1203 QTest::newRow( dataTag: "qdate" ) << QVariant( QDate( 2002, 10, 10 ) ) << QDateTime( QDate( 2002, 10, 10 ), QTime( 0, 0, 0 ) );
1204 QTest::newRow( dataTag: "qstring" ) << QVariant( QString( "2002-10-10T12:34:56" ) ) << QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56 ) );
1205 QTest::newRow( dataTag: "qstring-utc" ) << QVariant( QString( "2002-10-10T12:34:56Z" ) )
1206 << QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56 ), Qt::UTC );
1207 QTest::newRow( dataTag: "qstring-with-ms" ) << QVariant( QString( "2002-10-10T12:34:56.789" ) )
1208 << QDateTime( QDate( 2002, 10, 10 ), QTime( 12, 34, 56, 789 ) );
1209}
1210
1211void tst_QVariant::toDateTime()
1212{
1213 QFETCH( QVariant, value );
1214 QFETCH( QDateTime, result );
1215 QVERIFY( value.isValid() );
1216 QVERIFY( value.canConvert( QVariant::DateTime ) );
1217 QCOMPARE( value.toDateTime(), result );
1218}
1219
1220void tst_QVariant::toLocale()
1221{
1222 QVariant variant;
1223 QLocale loc = variant.toLocale();
1224 variant = QLocale::system();
1225 loc = variant.toLocale();
1226}
1227
1228void tst_QVariant::toRegExp()
1229{
1230 QVariant variant;
1231 QRegExp rx = variant.toRegExp();
1232 variant = QRegExp("foo");
1233 rx = variant.toRegExp();
1234}
1235
1236void tst_QVariant::toRegularExpression()
1237{
1238 QVariant variant;
1239 QRegularExpression re = variant.toRegularExpression();
1240 QCOMPARE(re, QRegularExpression());
1241
1242 variant = QRegularExpression("abc.*def");
1243 re = variant.toRegularExpression();
1244 QCOMPARE(re, QRegularExpression("abc.*def"));
1245
1246 variant = QVariant::fromValue(value: QRegularExpression("[ab]\\w+"));
1247 re = variant.value<QRegularExpression>();
1248 QCOMPARE(re, QRegularExpression("[ab]\\w+"));
1249}
1250
1251struct CustomStreamableClass
1252{
1253 int i;
1254 bool operator==(const CustomStreamableClass& other) const
1255 {
1256 return i == other.i;
1257 }
1258};
1259Q_DECLARE_METATYPE(CustomStreamableClass);
1260
1261QDataStream &operator<<(QDataStream &out, const CustomStreamableClass &myObj)
1262{
1263 return out << myObj.i;
1264}
1265
1266QDataStream &operator>>(QDataStream &in, CustomStreamableClass &myObj)
1267{
1268 return in >> myObj.i;
1269}
1270
1271void tst_QVariant::writeToReadFromDataStream_data()
1272{
1273 qRegisterMetaTypeStreamOperators<CustomStreamableClass>();
1274
1275 QTest::addColumn<QVariant>(name: "writeVariant");
1276 QTest::addColumn<bool>(name: "isNull");
1277 {
1278 QVariantList valuelist;
1279 valuelist << QVariant( 1 ) << QVariant( QString("Two") ) << QVariant( 3.45 );
1280 QVariant var(valuelist);
1281 QTest::newRow( dataTag: "list_valid" ) << var << false;
1282 }
1283
1284 QTest::newRow( dataTag: "invalid" ) << QVariant() << true;
1285 QTest::newRow( dataTag: "bitarray_invalid" ) << QVariant( QBitArray() ) << true;
1286 QBitArray bitarray( 3 );
1287 bitarray[0] = 0;
1288 bitarray[1] = 1;
1289 bitarray[2] = 0;
1290 QTest::newRow( dataTag: "bitarray_valid" ) << QVariant( bitarray ) << false;
1291 QTest::newRow( dataTag: "bytearray_invalid" ) << QVariant( QByteArray() ) << true;
1292 QTest::newRow( dataTag: "int_invalid") << QVariant(QVariant::Int) << true;
1293 QByteArray bytearray(5, ' ');
1294 bytearray[0] = 'T';
1295 bytearray[1] = 'e';
1296 bytearray[2] = 's';
1297 bytearray[3] = 't';
1298 bytearray[4] = '\0';
1299 QTest::newRow( dataTag: "bytearray_valid" ) << QVariant( bytearray ) << false;
1300 QTest::newRow( dataTag: "date_invalid" ) << QVariant( QDate() ) << true;
1301 QTest::newRow( dataTag: "date_valid" ) << QVariant( QDate( 2002, 07, 06 ) ) << false;
1302 QTest::newRow( dataTag: "datetime_invalid" ) << QVariant( QDateTime() ) << true;
1303 QTest::newRow( dataTag: "datetime_valid" ) << QVariant( QDateTime( QDate( 2002, 07, 06 ), QTime( 14, 0, 0 ) ) ) << false;
1304 QTest::newRow( dataTag: "double_valid" ) << QVariant( 123.456 ) << false;
1305 QTest::newRow( dataTag: "float_valid" ) << QVariant( 123.456f ) << false;
1306 QTest::newRow( dataTag: "int_valid" ) << QVariant( -123 ) << false;
1307 QVariantMap vMap;
1308 vMap.insert( akey: "int", avalue: QVariant( 1 ) );
1309 vMap.insert( akey: "string", avalue: QVariant( QString("Two") ) );
1310 vMap.insert( akey: "double", avalue: QVariant( 3.45 ) );
1311 vMap.insert( akey: "float", avalue: QVariant( 3.45f ) );
1312 QTest::newRow( dataTag: "map_valid" ) << QVariant( vMap ) << false;
1313 QTest::newRow( dataTag: "point_invalid" ) << QVariant::fromValue( value: QPoint() ) << true;
1314 QTest::newRow( dataTag: "point_valid" ) << QVariant::fromValue( value: QPoint( 10, 10 ) ) << false;
1315 QTest::newRow( dataTag: "rect_invalid" ) << QVariant( QRect() ) << true;
1316 QTest::newRow( dataTag: "rect_valid" ) << QVariant( QRect( 10, 10, 20, 20 ) ) << false;
1317 QTest::newRow( dataTag: "size_invalid" ) << QVariant( QSize( 0, 0 ) ) << true;
1318 QTest::newRow( dataTag: "size_valid" ) << QVariant( QSize( 10, 10 ) ) << false;
1319 QTest::newRow( dataTag: "string_invalid" ) << QVariant( QString() ) << true;
1320 QTest::newRow( dataTag: "string_valid" ) << QVariant( QString( "Test" ) ) << false;
1321 QStringList stringlist;
1322 stringlist << "One" << "Two" << "Three";
1323 QTest::newRow( dataTag: "stringlist_valid" ) << QVariant( stringlist ) << false;
1324 QTest::newRow( dataTag: "time_invalid" ) << QVariant( QTime() ) << true;
1325 QTest::newRow( dataTag: "time_valid" ) << QVariant( QTime( 14, 0, 0 ) ) << false;
1326 QTest::newRow( dataTag: "uint_valid" ) << QVariant( (uint)123 ) << false;
1327 QTest::newRow( dataTag: "qchar" ) << QVariant(QChar('a')) << false;
1328 QTest::newRow( dataTag: "qchar_null" ) << QVariant(QChar(0)) << true;
1329 QTest::newRow( dataTag: "regexp" ) << QVariant(QRegExp("foo", Qt::CaseInsensitive)) << false;
1330 QTest::newRow( dataTag: "regexp_empty" ) << QVariant(QRegExp()) << false;
1331 QTest::newRow( dataTag: "regularexpression" ) << QVariant(QRegularExpression("abc.*def")) << false;
1332 QTest::newRow( dataTag: "regularexpression_empty" ) << QVariant(QRegularExpression()) << false;
1333
1334 // types known to QMetaType, but not part of QVariant::Type
1335 QTest::newRow(dataTag: "QMetaType::Long invalid") << QVariant(QMetaType::Long, (void *) 0) << false;
1336 long longInt = -1l;
1337 QTest::newRow(dataTag: "QMetaType::Long") << QVariant(QMetaType::Long, &longInt) << false;
1338 QTest::newRow(dataTag: "QMetaType::Short invalid") << QVariant(QMetaType::Short, (void *) 0) << false;
1339 short shortInt = 1;
1340 QTest::newRow(dataTag: "QMetaType::Short") << QVariant(QMetaType::Short, &shortInt) << false;
1341 QTest::newRow(dataTag: "QMetaType::Char invalid") << QVariant(QMetaType::Char, (void *) 0) << false;
1342 char ch = 'c';
1343 QTest::newRow(dataTag: "QMetaType::Char") << QVariant(QMetaType::Char, &ch) << false;
1344 QTest::newRow(dataTag: "QMetaType::ULong invalid") << QVariant(QMetaType::ULong, (void *) 0) << false;
1345 ulong ulongInt = 1ul;
1346 QTest::newRow(dataTag: "QMetaType::ULong") << QVariant(QMetaType::ULong, &ulongInt) << false;
1347 QTest::newRow(dataTag: "QMetaType::UShort invalid") << QVariant(QMetaType::UShort, (void *) 0) << false;
1348 ushort ushortInt = 1u;
1349 QTest::newRow(dataTag: "QMetaType::UShort") << QVariant(QMetaType::UShort, &ushortInt) << false;
1350 QTest::newRow(dataTag: "QMetaType::UChar invalid") << QVariant(QMetaType::UChar, (void *) 0) << false;
1351 uchar uch = 0xf0;
1352 QTest::newRow(dataTag: "QMetaType::UChar") << QVariant(QMetaType::UChar, &uch) << false;
1353 QTest::newRow(dataTag: "QMetaType::Float invalid") << QVariant(QMetaType::Float, (void *) 0) << false;
1354 float f = 1.234f;
1355 QTest::newRow(dataTag: "QMetaType::Float") << QVariant(QMetaType::Float, &f) << false;
1356 CustomStreamableClass custom = {.i: 123};
1357 QTest::newRow(dataTag: "Custom type") << QVariant::fromValue(value: custom) << false;
1358}
1359
1360void tst_QVariant::writeToReadFromDataStream()
1361{
1362 QFETCH( QVariant, writeVariant );
1363 QFETCH( bool, isNull );
1364 QByteArray data;
1365
1366 QDataStream writeStream( &data, QIODevice::WriteOnly );
1367 writeStream << writeVariant;
1368
1369 QVariant readVariant;
1370 QDataStream readStream( &data, QIODevice::ReadOnly );
1371 readStream >> readVariant;
1372 QVERIFY( readVariant.isNull() == isNull );
1373 // Best way to confirm the readVariant contains the same data?
1374 // Since only a few won't match since the serial numbers are different
1375 // I won't bother adding another bool in the data test.
1376 const int writeType = writeVariant.userType();
1377 if (writeType == qMetaTypeId<CustomStreamableClass>())
1378 QCOMPARE(qvariant_cast<CustomStreamableClass>(readVariant), qvariant_cast<CustomStreamableClass>(writeVariant));
1379 else if ( writeType != QVariant::Invalid && writeType != QVariant::Bitmap && writeType != QVariant::Pixmap
1380 && writeType != QVariant::Image) {
1381 switch (writeType) {
1382 default:
1383 QCOMPARE( readVariant, writeVariant );
1384 break;
1385
1386 // compare types know by QMetaType but not QVariant (QVariant::operator==() knows nothing about them)
1387 case QMetaType::Long:
1388 QCOMPARE(qvariant_cast<long>(readVariant), qvariant_cast<long>(writeVariant));
1389 break;
1390 case QMetaType::ULong:
1391 QCOMPARE(qvariant_cast<ulong>(readVariant), qvariant_cast<ulong>(writeVariant));
1392 break;
1393 case QMetaType::Short:
1394 QCOMPARE(qvariant_cast<short>(readVariant), qvariant_cast<short>(writeVariant));
1395 break;
1396 case QMetaType::UShort:
1397 QCOMPARE(qvariant_cast<ushort>(readVariant), qvariant_cast<ushort>(writeVariant));
1398 break;
1399 case QMetaType::Char:
1400 QCOMPARE(qvariant_cast<char>(readVariant), qvariant_cast<char>(writeVariant));
1401 break;
1402 case QMetaType::UChar:
1403 QCOMPARE(qvariant_cast<uchar>(readVariant), qvariant_cast<uchar>(writeVariant));
1404 break;
1405 case QMetaType::Float:
1406 {
1407 // the uninitialized float can be NaN (observed on Windows Mobile 5 ARMv4i)
1408 float readFloat = qvariant_cast<float>(v: readVariant);
1409 float writtenFloat = qvariant_cast<float>(v: writeVariant);
1410 QCOMPARE(qIsNaN(readFloat), qIsNaN(writtenFloat));
1411 if (!qIsNaN(f: readFloat))
1412 QCOMPARE(readFloat, writtenFloat);
1413 }
1414 break;
1415 }
1416 }
1417}
1418
1419void tst_QVariant::writeToReadFromOldDataStream()
1420{
1421 QVariant writeVariant = QString("hello");
1422 QByteArray data;
1423
1424 QDataStream writeStream(&data, QIODevice::WriteOnly);
1425 writeStream.setVersion(QDataStream::Qt_2_1);
1426 writeStream << writeVariant;
1427
1428 QVariant readVariant;
1429 QDataStream readStream(&data, QIODevice::ReadOnly);
1430 readStream.setVersion(QDataStream::Qt_2_1);
1431 readStream >> readVariant;
1432
1433 QCOMPARE(writeVariant.userType(), readVariant.userType());
1434 QCOMPARE(writeVariant, readVariant);
1435}
1436
1437void tst_QVariant::checkDataStream()
1438{
1439 const int typeId = QMetaType::LastCoreType + 1;
1440 QVERIFY(!QMetaType::isRegistered(typeId));
1441
1442 QByteArray errorMessage("Trying to construct an instance of an invalid type, type id: ");
1443 errorMessage.append(a: QString::number(typeId, base: 10).toUtf8());
1444
1445 QTest::ignoreMessage(type: QtWarningMsg, message: errorMessage.constData());
1446 QByteArray settingsHex("000000");
1447 settingsHex.append(a: QString::number(typeId, base: 16).toUtf8());
1448 settingsHex.append(s: "ffffffffff");
1449 const QByteArray settings = QByteArray::fromHex(hexEncoded: settingsHex);
1450 QDataStream in(settings);
1451 QVariant v;
1452 in >> v;
1453 // the line below has been left out for now since the data stream
1454 // is not necessarily considered corrupt when an invalid QVariant is
1455 // constructed. However, it might be worth considering changing that behavior
1456 // in the future.
1457// QCOMPARE(in.status(), QDataStream::ReadCorruptData);
1458 QCOMPARE(v.type(), QVariant::Invalid);
1459}
1460
1461void tst_QVariant::operator_eq_eq_data()
1462{
1463 QTest::addColumn<QVariant>(name: "left");
1464 QTest::addColumn<QVariant>(name: "right");
1465 QTest::addColumn<bool>(name: "equal"); // left == right ?
1466
1467 QVariant inv;
1468 QVariant i0( int(0) );
1469 QVariant i1( int(1) );
1470 // Invalid
1471 QTest::newRow( dataTag: "invinv" ) << inv << inv << true;
1472 // Int
1473 QTest::newRow( dataTag: "int1int1" ) << i1 << i1 << true;
1474 QTest::newRow( dataTag: "int1int0" ) << i1 << i0 << false;
1475 QTest::newRow( dataTag: "nullint" ) << i0 << QVariant(QVariant::Int) << true;
1476
1477 // LongLong and ULongLong
1478 QVariant ll1( (qlonglong)1 );
1479 QVariant lln2( (qlonglong)-2 );
1480 QVariant ull1( (qulonglong)1 );
1481 QVariant ull3( (qulonglong)3 );
1482 QTest::newRow( dataTag: "ll1ll1" ) << ll1 << ll1 << true;
1483 QTest::newRow( dataTag: "ll1lln2" ) << ll1 << lln2 << false;
1484 QTest::newRow( dataTag: "ll1ull1" ) << ull1 << ull1 << true;
1485 QTest::newRow( dataTag: "ll1i1" ) << ull1 << i1 << true;
1486 QTest::newRow( dataTag: "ull1ull1" ) << ull1 << ull1 << true;
1487 QTest::newRow( dataTag: "ull1i1" ) << ull1 << ull1 << true;
1488
1489 QVariant mInt(-42);
1490 QVariant mIntString(QByteArray("-42"));
1491 QVariant mIntQString(QString("-42"));
1492
1493 QVariant mUInt(42u);
1494 QVariant mUIntString(QByteArray("42"));
1495 QVariant mUIntQString(QString("42"));
1496
1497 QVariant mDouble(42.11);
1498#ifdef QT_NO_DOUBLECONVERSION
1499 // Without libdouble-conversion we don't get the shortest possible representation.
1500 QVariant mDoubleString(QByteArray("42.109999999999999"));
1501 QVariant mDoubleQString(QByteArray("42.109999999999999"));
1502#else
1503 // You cannot fool the double-to-string conversion into producing insignificant digits with
1504 // libdouble-conversion. You can, of course, add insignificant digits to the string and fool
1505 // the double-to-double comparison after converting the string to a double.
1506 QVariant mDoubleString(QByteArray("42.11"));
1507 QVariant mDoubleQString(QString("42.11"));
1508#endif
1509
1510 // Float-to-double conversion produces insignificant extra bits.
1511 QVariant mFloat(42.11f);
1512#ifdef QT_NO_DOUBLECONVERSION
1513 // The trailing '2' is not significant, but snprintf doesn't know this.
1514 QVariant mFloatString(QByteArray("42.110000610351562"));
1515 QVariant mFloatQString(QString("42.110000610351562"));
1516#else
1517 QVariant mFloatString(QByteArray("42.11000061035156"));
1518 QVariant mFloatQString(QString("42.11000061035156"));
1519#endif
1520
1521 QVariant mLongLong((qlonglong)-42);
1522 QVariant mLongLongString(QByteArray("-42"));
1523 QVariant mLongLongQString(QString("-42"));
1524
1525 QVariant mULongLong((qulonglong)42);
1526 QVariant mULongLongString(QByteArray("42"));
1527 QVariant mULongLongQString(QString("42"));
1528
1529 QVariant mBool(false);
1530 QVariant mBoolString(QByteArray("false"));
1531 QVariant mBoolQString(QString("false"));
1532
1533 QTest::newRow( dataTag: "double_int" ) << QVariant(42.0) << QVariant(42) << true;
1534 QTest::newRow( dataTag: "float_int" ) << QVariant(42.f) << QVariant(42) << true;
1535 QTest::newRow( dataTag: "mInt_mIntString" ) << mInt << mIntString << true;
1536 QTest::newRow( dataTag: "mIntString_mInt" ) << mIntString << mInt << true;
1537 QTest::newRow( dataTag: "mInt_mIntQString" ) << mInt << mIntQString << true;
1538 QTest::newRow( dataTag: "mIntQString_mInt" ) << mIntQString << mInt << true;
1539
1540 QTest::newRow( dataTag: "mUInt_mUIntString" ) << mUInt << mUIntString << true;
1541 QTest::newRow( dataTag: "mUIntString_mUInt" ) << mUIntString << mUInt << true;
1542 QTest::newRow( dataTag: "mUInt_mUIntQString" ) << mUInt << mUIntQString << true;
1543 QTest::newRow( dataTag: "mUIntQString_mUInt" ) << mUIntQString << mUInt << true;
1544
1545 QTest::newRow( dataTag: "mDouble_mDoubleString" ) << mDouble << mDoubleString << true;
1546 QTest::newRow( dataTag: "mDoubleString_mDouble" ) << mDoubleString << mDouble << true;
1547 QTest::newRow( dataTag: "mDouble_mDoubleQString" ) << mDouble << mDoubleQString << true;
1548 QTest::newRow( dataTag: "mDoubleQString_mDouble" ) << mDoubleQString << mDouble << true;
1549
1550 QTest::newRow( dataTag: "mFloat_mFloatString" ) << mFloat << mFloatString << true;
1551 QTest::newRow( dataTag: "mFloatString_mFloat" ) << mFloatString << mFloat << true;
1552 QTest::newRow( dataTag: "mFloat_mFloatQString" ) << mFloat << mFloatQString << true;
1553 QTest::newRow( dataTag: "mFloatQString_mFloat" ) << mFloatQString << mFloat << true;
1554
1555 QTest::newRow( dataTag: "mLongLong_mLongLongString" ) << mLongLong << mLongLongString << true;
1556 QTest::newRow( dataTag: "mLongLongString_mLongLong" ) << mLongLongString << mLongLong << true;
1557 QTest::newRow( dataTag: "mLongLong_mLongLongQString" ) << mLongLong << mLongLongQString << true;
1558 QTest::newRow( dataTag: "mLongLongQString_mLongLong" ) << mLongLongQString << mLongLong << true;
1559
1560 QTest::newRow( dataTag: "mULongLong_mULongLongString" ) << mULongLong << mULongLongString << true;
1561 QTest::newRow( dataTag: "mULongLongString_mULongLong" ) << mULongLongString << mULongLong << true;
1562 QTest::newRow( dataTag: "mULongLong_mULongLongQString" ) << mULongLong << mULongLongQString << true;
1563 QTest::newRow( dataTag: "mULongLongQString_mULongLong" ) << mULongLongQString << mULongLong << true;
1564
1565 QTest::newRow( dataTag: "mBool_mBoolString" ) << mBool << mBoolString << true;
1566 QTest::newRow( dataTag: "mBoolString_mBool" ) << mBoolString << mBool << true;
1567 QTest::newRow( dataTag: "mBool_mBoolQString" ) << mBool << mBoolQString << true;
1568 QTest::newRow( dataTag: "mBoolQString_mBool" ) << mBoolQString << mBool << true;
1569
1570 QTest::newRow(dataTag: "ba2qstring") << QVariant(QLatin1String("hallo")) << QVariant(QString("hallo")) << true;
1571 QTest::newRow(dataTag: "qstring2ba") << QVariant(QString("hallo")) << QVariant(QLatin1String("hallo")) << true;
1572 QTest::newRow(dataTag: "char_char") << QVariant(QChar('a')) << QVariant(QChar('a')) << true;
1573 QTest::newRow(dataTag: "char_char2") << QVariant(QChar('a')) << QVariant(QChar('b')) << false;
1574
1575 QTest::newRow(dataTag: "invalidConversion") << QVariant(QString("bubu")) << QVariant(0) << false;
1576 QTest::newRow(dataTag: "invalidConversionR") << QVariant(0) << QVariant(QString("bubu")) << false;
1577 // ### many other combinations missing
1578
1579 {
1580 QUuid uuid(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1581 QTest::newRow(dataTag: "uuidstring") << QVariant(uuid) << QVariant(uuid.toString()) << true;
1582 QTest::newRow(dataTag: "stringuuid") << QVariant(uuid.toString()) << QVariant(uuid) << true;
1583 QTest::newRow(dataTag: "uuidbytearray") << QVariant(uuid) << QVariant(uuid.toByteArray()) << true;
1584 QTest::newRow(dataTag: "bytearrayuuid") << QVariant(uuid.toByteArray()) << QVariant(uuid) << true;
1585 }
1586
1587 {
1588 QMap<QString, QVariant> map1;
1589 map1.insert( akey: "X", avalue: 1 );
1590
1591 QMap<QString, QVariant> map2;
1592 map2.insert( akey: "Y", avalue: 1 );
1593
1594 QTest::newRow(dataTag: "TwoItemsInEqual") << QVariant(map1) << QVariant(map2) << false;
1595
1596 }
1597
1598 {
1599 QMap<QString, QVariant> map1;
1600 map1.insert( akey: "X", avalue: 1 );
1601
1602 QMap<QString, QVariant> map2;
1603 map2.insert( akey: "X", avalue: 1 );
1604
1605 QTest::newRow(dataTag: "TwoItemsEqual") << QVariant(map1) << QVariant(map2) << true;
1606 }
1607
1608 {
1609 QMap<QString, QVariant> map1;
1610 map1.insert( akey: "X", avalue: 1 );
1611
1612 QMap<QString, QVariant> map2;
1613
1614 QTest::newRow(dataTag: "PopulatedEmptyMap") << QVariant(map1) << QVariant(map2) << false;
1615 }
1616
1617 {
1618 QMap<QString, QVariant> map1;
1619
1620 QMap<QString, QVariant> map2;
1621 map2.insert( akey: "X", avalue: 1 );
1622
1623 QTest::newRow(dataTag: "EmptyPopulatedMap") << QVariant(map1) << QVariant(map2) << false;
1624 }
1625
1626 {
1627 QMap<QString, QVariant> map1;
1628 map1.insert( akey: "X", avalue: 1 );
1629 map1.insert( akey: "Y", avalue: 1 );
1630
1631 QMap<QString, QVariant> map2;
1632 map2.insert( akey: "X", avalue: 1 );
1633
1634 QTest::newRow(dataTag: "FirstLarger") << QVariant(map1) << QVariant(map2) << false;
1635 }
1636
1637 {
1638 QMap<QString, QVariant> map1;
1639 map1.insert( akey: "X", avalue: 1 );
1640
1641 QMap<QString, QVariant> map2;
1642 map2.insert( akey: "X", avalue: 1 );
1643 map2.insert( akey: "Y", avalue: 1 );
1644
1645 QTest::newRow(dataTag: "SecondLarger") << QVariant(map1) << QVariant(map2) << false;
1646 }
1647
1648 // same thing with hash
1649 {
1650 QHash<QString, QVariant> hash1;
1651 hash1.insert( akey: "X", avalue: 1 );
1652
1653 QHash<QString, QVariant> hash2;
1654 hash2.insert( akey: "Y", avalue: 1 );
1655
1656 QTest::newRow(dataTag: "HashTwoItemsInEqual") << QVariant(hash1) << QVariant(hash2) << false;
1657
1658 }
1659
1660 {
1661 QHash<QString, QVariant> hash1;
1662 hash1.insert( akey: "X", avalue: 1 );
1663
1664 QHash<QString, QVariant> hash2;
1665 hash2.insert( akey: "X", avalue: 1 );
1666
1667 QTest::newRow(dataTag: "HashTwoItemsEqual") << QVariant(hash1) << QVariant(hash2) << true;
1668 }
1669
1670 {
1671 QHash<QString, QVariant> hash1;
1672 hash1.insert( akey: "X", avalue: 1 );
1673
1674 QHash<QString, QVariant> hash2;
1675
1676 QTest::newRow(dataTag: "HashPopulatedEmptyHash") << QVariant(hash1) << QVariant(hash2) << false;
1677 }
1678
1679 {
1680 QHash<QString, QVariant> hash1;
1681
1682 QHash<QString, QVariant> hash2;
1683 hash2.insert( akey: "X", avalue: 1 );
1684
1685 QTest::newRow(dataTag: "EmptyPopulatedHash") << QVariant(hash1) << QVariant(hash2) << false;
1686 }
1687
1688 {
1689 QHash<QString, QVariant> hash1;
1690 hash1.insert( akey: "X", avalue: 1 );
1691 hash1.insert( akey: "Y", avalue: 1 );
1692
1693 QHash<QString, QVariant> hash2;
1694 hash2.insert( akey: "X", avalue: 1 );
1695
1696 QTest::newRow(dataTag: "HashFirstLarger") << QVariant(hash1) << QVariant(hash2) << false;
1697 }
1698
1699 {
1700 QHash<QString, QVariant> hash1;
1701 hash1.insert( akey: "X", avalue: 1 );
1702
1703 QHash<QString, QVariant> hash2;
1704 hash2.insert( akey: "X", avalue: 1 );
1705 hash2.insert( akey: "Y", avalue: 1 );
1706
1707 QTest::newRow(dataTag: "HashSecondLarger") << QVariant(hash1) << QVariant(hash2) << false;
1708 }
1709}
1710
1711void tst_QVariant::operator_eq_eq()
1712{
1713 QFETCH( QVariant, left );
1714 QFETCH( QVariant, right );
1715 QFETCH( bool, equal );
1716 QCOMPARE( left == right, equal );
1717}
1718
1719void tst_QVariant::operator_eq_eq_rhs()
1720{
1721 QVariant v = 42;
1722
1723 QVERIFY(v == 42);
1724 QVERIFY(42 == v);
1725
1726#if 0
1727 /* This should _not_ compile */
1728 QStringList list;
1729 QDateTime dt;
1730
1731 QVERIFY(dt == list);
1732#endif
1733}
1734
1735void tst_QVariant::compareNumbers_data() const
1736{
1737 typedef signed char schar;
1738 QTest::addColumn<QVariant>(name: "v1");
1739 QTest::addColumn<QVariant>(name: "v2");
1740 QTest::addColumn<int>(name: "expected");
1741
1742 // sanity checking: same types
1743 QTest::newRow(dataTag: "bool1") << QVariant(false) << QVariant(false) << 0;
1744 QTest::newRow(dataTag: "bool2") << QVariant(true) << QVariant(true) << 0;
1745 QTest::newRow(dataTag: "bool3") << QVariant(false) << QVariant(true) << -1;
1746 QTest::newRow(dataTag: "bool4") << QVariant(true) << QVariant(false) << +1;
1747
1748 QTest::newRow(dataTag: "char1") << QVariant::fromValue(value: char(0)) << QVariant::fromValue(value: char(0)) << 0;
1749 QTest::newRow(dataTag: "char2") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(CHAR_MAX) << 0;
1750 QTest::newRow(dataTag: "char3") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(CHAR_MIN) << 0;
1751 QTest::newRow(dataTag: "char4") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(CHAR_MAX) << -1;
1752 QTest::newRow(dataTag: "char5") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(CHAR_MIN) << +1;
1753
1754 QTest::newRow(dataTag: "schar1") << QVariant::fromValue(value: schar(0)) << QVariant::fromValue(value: schar(0)) << 0;
1755 QTest::newRow(dataTag: "schar2") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(SCHAR_MAX) << 0;
1756 QTest::newRow(dataTag: "schar3") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(SCHAR_MIN) << 0;
1757 QTest::newRow(dataTag: "schar4") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(SCHAR_MAX) << -1;
1758 QTest::newRow(dataTag: "schar5") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(SCHAR_MIN) << +1;
1759
1760 QTest::newRow(dataTag: "uchar1") << QVariant::fromValue(value: uchar(0)) << QVariant::fromValue(value: uchar(0)) << 0;
1761 QTest::newRow(dataTag: "uchar2") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(UCHAR_MAX) << 0;
1762 QTest::newRow(dataTag: "uchar3") << QVariant::fromValue(value: uchar(0)) << QVariant::fromValue(UCHAR_MAX) << -1;
1763 QTest::newRow(dataTag: "uchar4") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(value: uchar(0)) << +1;
1764
1765 QTest::newRow(dataTag: "short1") << QVariant::fromValue(value: short(0)) << QVariant::fromValue(value: short(0)) << 0;
1766 QTest::newRow(dataTag: "short2") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(SHRT_MAX) << 0;
1767 QTest::newRow(dataTag: "short3") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(SHRT_MIN) << 0;
1768 QTest::newRow(dataTag: "short4") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(SHRT_MAX) << -1;
1769 QTest::newRow(dataTag: "short5") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(SHRT_MIN) << +1;
1770
1771 QTest::newRow(dataTag: "ushort1") << QVariant::fromValue(value: ushort(0)) << QVariant::fromValue(value: ushort(0)) << 0;
1772 QTest::newRow(dataTag: "ushort2") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(USHRT_MAX) << 0;
1773 QTest::newRow(dataTag: "ushort3") << QVariant::fromValue(value: ushort(0)) << QVariant::fromValue(USHRT_MAX) << -1;
1774 QTest::newRow(dataTag: "ushort4") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(value: ushort(0)) << +1;
1775
1776 QTest::newRow(dataTag: "int1") << QVariant::fromValue(value: int(0)) << QVariant::fromValue(value: int(0)) << 0;
1777 QTest::newRow(dataTag: "int2") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(INT_MAX) << 0;
1778 QTest::newRow(dataTag: "int3") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(INT_MIN) << 0;
1779 QTest::newRow(dataTag: "int4") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(INT_MAX) << -1;
1780 QTest::newRow(dataTag: "int5") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(INT_MIN) << +1;
1781
1782 QTest::newRow(dataTag: "uint1") << QVariant::fromValue(value: uint(0)) << QVariant::fromValue(value: uint(0)) << 0;
1783 QTest::newRow(dataTag: "uint2") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(UINT_MAX) << 0;
1784 QTest::newRow(dataTag: "uint3") << QVariant::fromValue(value: uint(0)) << QVariant::fromValue(UINT_MAX) << -1;
1785 QTest::newRow(dataTag: "uint4") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(value: uint(0)) << +1;
1786
1787 QTest::newRow(dataTag: "long1") << QVariant::fromValue(value: long(0)) << QVariant::fromValue(value: long(0)) << 0;
1788 QTest::newRow(dataTag: "long2") << QVariant::fromValue(LONG_MAX) << QVariant::fromValue(LONG_MAX) << 0;
1789 QTest::newRow(dataTag: "long3") << QVariant::fromValue(LONG_MIN) << QVariant::fromValue(LONG_MIN) << 0;
1790 QTest::newRow(dataTag: "long4") << QVariant::fromValue(LONG_MIN) << QVariant::fromValue(LONG_MAX) << -1;
1791 QTest::newRow(dataTag: "long5") << QVariant::fromValue(LONG_MAX) << QVariant::fromValue(LONG_MIN) << +1;
1792
1793 QTest::newRow(dataTag: "ulong1") << QVariant::fromValue(value: ulong(0)) << QVariant::fromValue(value: ulong(0)) << 0;
1794 QTest::newRow(dataTag: "ulong2") << QVariant::fromValue(ULONG_MAX) << QVariant::fromValue(ULONG_MAX) << 0;
1795 QTest::newRow(dataTag: "ulong3") << QVariant::fromValue(value: ulong(0)) << QVariant::fromValue(ULONG_MAX) << -1;
1796 QTest::newRow(dataTag: "ulong4") << QVariant::fromValue(ULONG_MAX) << QVariant::fromValue(value: ulong(0)) << +1;
1797
1798 QTest::newRow(dataTag: "llong1") << QVariant::fromValue(value: qlonglong(0)) << QVariant::fromValue(value: qlonglong(0)) << 0;
1799 QTest::newRow(dataTag: "llong2") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(LLONG_MAX) << 0;
1800 QTest::newRow(dataTag: "llong3") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(LLONG_MIN) << 0;
1801 QTest::newRow(dataTag: "llong4") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(LLONG_MAX) << -1;
1802 QTest::newRow(dataTag: "llong5") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(LLONG_MIN) << +1;
1803
1804 QTest::newRow(dataTag: "ullong1") << QVariant::fromValue(value: qulonglong(0)) << QVariant::fromValue(value: qulonglong(0)) << 0;
1805 QTest::newRow(dataTag: "ullong2") << QVariant::fromValue(ULLONG_MAX) << QVariant::fromValue(ULLONG_MAX) << 0;
1806 QTest::newRow(dataTag: "ullong3") << QVariant::fromValue(value: qulonglong(0)) << QVariant::fromValue(ULLONG_MAX) << -1;
1807 QTest::newRow(dataTag: "ullong4") << QVariant::fromValue(ULLONG_MAX) << QVariant::fromValue(value: qulonglong(0)) << +1;
1808
1809 QTest::newRow(dataTag: "float1") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: 0.f) << 0;
1810 QTest::newRow(dataTag: "float2") << QVariant::fromValue(value: -1.f) << QVariant::fromValue(value: 0.f) << -1;
1811 QTest::newRow(dataTag: "float3") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: -1.f) << +1;
1812 QTest::newRow(dataTag: "float4") << QVariant::fromValue(value: -float(qInf())) << QVariant::fromValue(value: 0.f) << -1;
1813 QTest::newRow(dataTag: "float5") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: -float(qInf())) << +1;
1814 QTest::newRow(dataTag: "float6") << QVariant::fromValue(value: -float(qInf())) << QVariant::fromValue(value: -float(qInf())) << 0;
1815 QTest::newRow(dataTag: "float7") << QVariant::fromValue(value: float(qInf())) << QVariant::fromValue(value: float(qInf())) << 0;
1816
1817 QTest::newRow(dataTag: "double1") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: 0.) << 0;
1818 QTest::newRow(dataTag: "double2") << QVariant::fromValue(value: -1.) << QVariant::fromValue(value: 0.) << -1;
1819 QTest::newRow(dataTag: "double3") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: -1.) << +1;
1820 QTest::newRow(dataTag: "double4") << QVariant::fromValue(value: -qInf()) << QVariant::fromValue(value: 0.) << -1;
1821 QTest::newRow(dataTag: "double5") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: -qInf()) << +1;
1822 QTest::newRow(dataTag: "double6") << QVariant::fromValue(value: -double(qInf())) << QVariant::fromValue(value: -qInf()) << 0;
1823 QTest::newRow(dataTag: "double7") << QVariant::fromValue(value: qInf()) << QVariant::fromValue(value: qInf()) << 0;
1824 QTest::newRow(dataTag: "double8") << QVariant::fromValue(value: -qInf()) << QVariant::fromValue(value: qInf()) << -1;
1825 QTest::newRow(dataTag: "double9") << QVariant::fromValue(value: qQNaN()) << QVariant::fromValue(value: 0.) << INT_MAX;
1826 QTest::newRow(dataTag: "double10") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: qQNaN()) << INT_MAX;
1827 QTest::newRow(dataTag: "double11") << QVariant::fromValue(value: qQNaN()) << QVariant::fromValue(value: qQNaN()) << INT_MAX;
1828
1829 // mixed comparisons
1830 // fp + fp
1831 QTest::newRow(dataTag: "float+double1") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: 0.) << 0;
1832 QTest::newRow(dataTag: "float+double2") << QVariant::fromValue(value: -1.f) << QVariant::fromValue(value: 0.) << -1;
1833 QTest::newRow(dataTag: "float+double3") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: -1.) << +1;
1834 QTest::newRow(dataTag: "float+double4") << QVariant::fromValue(value: -float(qInf())) << QVariant::fromValue(value: 0.) << -1;
1835 QTest::newRow(dataTag: "float+double5") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: -qInf()) << +1;
1836 QTest::newRow(dataTag: "float+double6") << QVariant::fromValue(value: -float(qInf())) << QVariant::fromValue(value: -qInf()) << 0;
1837 QTest::newRow(dataTag: "float+double7") << QVariant::fromValue(value: float(qInf())) << QVariant::fromValue(value: qInf()) << 0;
1838 QTest::newRow(dataTag: "float+double8") << QVariant::fromValue(value: -float(qInf())) << QVariant::fromValue(value: qInf()) << -1;
1839 QTest::newRow(dataTag: "float+double9") << QVariant::fromValue(value: qQNaN()) << QVariant::fromValue(value: 0.) << INT_MAX;
1840 QTest::newRow(dataTag: "float+double10") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: qQNaN()) << INT_MAX;
1841 QTest::newRow(dataTag: "float+double11") << QVariant::fromValue(value: qQNaN()) << QVariant::fromValue(value: qQNaN()) << INT_MAX;
1842
1843 // fp + int
1844 QTest::newRow(dataTag: "float+int1") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: 0) << 0;
1845 QTest::newRow(dataTag: "double+int1") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: 0) << 0;
1846 QTest::newRow(dataTag: "float+int2") << QVariant::fromValue(value: -1.f) << QVariant::fromValue(value: 0) << -1;
1847 QTest::newRow(dataTag: "double+int2") << QVariant::fromValue(value: -1.) << QVariant::fromValue(value: 0) << -1;
1848 QTest::newRow(dataTag: "float+int3") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: -1) << +1;
1849 QTest::newRow(dataTag: "double+int3") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: -1) << +1;
1850 QTest::newRow(dataTag: "float+int4") << QVariant::fromValue(value: 1.5f) << QVariant::fromValue(value: 1) << +1;
1851 QTest::newRow(dataTag: "double+int4") << QVariant::fromValue(value: 1.5) << QVariant::fromValue(value: 1) << +1;
1852 QTest::newRow(dataTag: "double+int5") << QVariant::fromValue(value: qInf()) << QVariant::fromValue(value: 1) << +1;
1853
1854 // fp + uint
1855 QTest::newRow(dataTag: "float+uint1") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: 0U) << 0;
1856 QTest::newRow(dataTag: "double+uint1") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: 0U) << 0;
1857 QTest::newRow(dataTag: "float+uint2") << QVariant::fromValue(value: -1.f) << QVariant::fromValue(value: 0U) << -1;
1858 QTest::newRow(dataTag: "double+uint2") << QVariant::fromValue(value: -1.) << QVariant::fromValue(value: 0U) << -1;
1859 QTest::newRow(dataTag: "float+uint3") << QVariant::fromValue(value: 0.f) << QVariant::fromValue(value: 1U) << -1;
1860 QTest::newRow(dataTag: "double+uint3") << QVariant::fromValue(value: 0.) << QVariant::fromValue(value: 1U) << -1;
1861 QTest::newRow(dataTag: "float+uint4") << QVariant::fromValue(value: 1.5f) << QVariant::fromValue(value: 1U) << +1;
1862 QTest::newRow(dataTag: "double+uint4") << QVariant::fromValue(value: 1.5) << QVariant::fromValue(value: 1U) << +1;
1863
1864 // lower ranked + int
1865 QTest::newRow(dataTag: "bool+int1") << QVariant::fromValue(value: false) << QVariant::fromValue(value: 0) << 0;
1866 QTest::newRow(dataTag: "bool+int2") << QVariant::fromValue(value: false) << QVariant::fromValue(value: 1) << -1;
1867 QTest::newRow(dataTag: "bool+int3") << QVariant::fromValue(value: true) << QVariant::fromValue(value: 0) << +1;
1868 QTest::newRow(dataTag: "bool+int4") << QVariant::fromValue(value: true) << QVariant::fromValue(value: 1) << 0;
1869 QTest::newRow(dataTag: "bool+int5") << QVariant::fromValue(value: true) << QVariant::fromValue(value: 2) << -1;
1870
1871 QTest::newRow(dataTag: "char+int1") << QVariant::fromValue(value: char(0)) << QVariant::fromValue(value: 0) << 0;
1872 QTest::newRow(dataTag: "char+int2") << QVariant::fromValue(value: char(0)) << QVariant::fromValue(value: 1) << -1;
1873 QTest::newRow(dataTag: "char+int3") << QVariant::fromValue(value: char(1)) << QVariant::fromValue(value: 0) << +1;
1874 QTest::newRow(dataTag: "char+int4") << QVariant::fromValue(value: char(1)) << QVariant::fromValue(value: 1) << 0;
1875 if (std::numeric_limits<char>::is_signed) {
1876 QTest::newRow(dataTag: "char+int5") << QVariant::fromValue(value: char(-1)) << QVariant::fromValue(value: 0) << -1;
1877 QTest::newRow(dataTag: "char+int6") << QVariant::fromValue(value: char(-1)) << QVariant::fromValue(value: -1) << 0;
1878 }
1879
1880 QTest::newRow(dataTag: "schar+int1") << QVariant::fromValue(value: schar(0)) << QVariant::fromValue(value: 0) << 0;
1881 QTest::newRow(dataTag: "schar+int2") << QVariant::fromValue(value: schar(0)) << QVariant::fromValue(value: 1) << -1;
1882 QTest::newRow(dataTag: "schar+int3") << QVariant::fromValue(value: schar(1)) << QVariant::fromValue(value: 0) << +1;
1883 QTest::newRow(dataTag: "schar+int4") << QVariant::fromValue(value: schar(1)) << QVariant::fromValue(value: 1) << 0;
1884 QTest::newRow(dataTag: "schar+int5") << QVariant::fromValue(value: schar(-1)) << QVariant::fromValue(value: 0) << -1;
1885 QTest::newRow(dataTag: "schar+int6") << QVariant::fromValue(value: schar(-1)) << QVariant::fromValue(value: -1) << 0;
1886
1887 QTest::newRow(dataTag: "uchar+int1") << QVariant::fromValue(value: uchar(0)) << QVariant::fromValue(value: 0) << 0;
1888 QTest::newRow(dataTag: "uchar+int2") << QVariant::fromValue(value: uchar(0)) << QVariant::fromValue(value: 1) << -1;
1889 QTest::newRow(dataTag: "uchar+int3") << QVariant::fromValue(value: uchar(1)) << QVariant::fromValue(value: 0) << +1;
1890 QTest::newRow(dataTag: "uchar+int4") << QVariant::fromValue(value: uchar(1)) << QVariant::fromValue(value: 1) << 0;
1891
1892 QTest::newRow(dataTag: "short+int1") << QVariant::fromValue(value: short(0)) << QVariant::fromValue(value: 0) << 0;
1893 QTest::newRow(dataTag: "short+int2") << QVariant::fromValue(value: short(0)) << QVariant::fromValue(value: 1) << -1;
1894 QTest::newRow(dataTag: "short+int3") << QVariant::fromValue(value: short(1)) << QVariant::fromValue(value: 0) << +1;
1895 QTest::newRow(dataTag: "short+int4") << QVariant::fromValue(value: short(1)) << QVariant::fromValue(value: 1) << 0;
1896 QTest::newRow(dataTag: "short+int5") << QVariant::fromValue(value: short(-1)) << QVariant::fromValue(value: 0) << -1;
1897 QTest::newRow(dataTag: "short+int6") << QVariant::fromValue(value: short(-1)) << QVariant::fromValue(value: -1) << 0;
1898
1899 QTest::newRow(dataTag: "ushort+int1") << QVariant::fromValue(value: ushort(0)) << QVariant::fromValue(value: 0) << 0;
1900 QTest::newRow(dataTag: "ushort+int2") << QVariant::fromValue(value: ushort(0)) << QVariant::fromValue(value: 1) << -1;
1901 QTest::newRow(dataTag: "ushort+int3") << QVariant::fromValue(value: ushort(1)) << QVariant::fromValue(value: 0) << +1;
1902 QTest::newRow(dataTag: "ushort+int4") << QVariant::fromValue(value: ushort(1)) << QVariant::fromValue(value: 1) << 0;
1903
1904 // lower ranked + uint (without sign change)
1905 QTest::newRow(dataTag: "bool+uint1") << QVariant::fromValue(value: false) << QVariant::fromValue(value: 0U) << 0;
1906 QTest::newRow(dataTag: "bool+uint2") << QVariant::fromValue(value: false) << QVariant::fromValue(value: 1U) << -1;
1907 QTest::newRow(dataTag: "bool+uint3") << QVariant::fromValue(value: true) << QVariant::fromValue(value: 0U) << +1;
1908 QTest::newRow(dataTag: "bool+uint4") << QVariant::fromValue(value: true) << QVariant::fromValue(value: 1U) << 0;
1909 QTest::newRow(dataTag: "bool+uint5") << QVariant::fromValue(value: true) << QVariant::fromValue(value: 2U) << -1;
1910
1911 QTest::newRow(dataTag: "char+uint1") << QVariant::fromValue(value: char(0)) << QVariant::fromValue(value: 0U) << 0;
1912 QTest::newRow(dataTag: "char+uint2") << QVariant::fromValue(value: char(0)) << QVariant::fromValue(value: 1U) << -1;
1913 QTest::newRow(dataTag: "char+uint3") << QVariant::fromValue(value: char(1)) << QVariant::fromValue(value: 0U) << +1;
1914 QTest::newRow(dataTag: "char+uint4") << QVariant::fromValue(value: char(1)) << QVariant::fromValue(value: 1U) << 0;
1915
1916 QTest::newRow(dataTag: "schar+uint1") << QVariant::fromValue(value: schar(0)) << QVariant::fromValue(value: 0U) << 0;
1917 QTest::newRow(dataTag: "schar+uint2") << QVariant::fromValue(value: schar(0)) << QVariant::fromValue(value: 1U) << -1;
1918 QTest::newRow(dataTag: "schar+uint3") << QVariant::fromValue(value: schar(1)) << QVariant::fromValue(value: 0U) << +1;
1919 QTest::newRow(dataTag: "schar+uint4") << QVariant::fromValue(value: schar(1)) << QVariant::fromValue(value: 1U) << 0;
1920
1921 QTest::newRow(dataTag: "uchar+uint1") << QVariant::fromValue(value: uchar(0)) << QVariant::fromValue(value: 0U) << 0;
1922 QTest::newRow(dataTag: "uchar+uint2") << QVariant::fromValue(value: uchar(0)) << QVariant::fromValue(value: 1U) << -1;
1923 QTest::newRow(dataTag: "uchar+uint3") << QVariant::fromValue(value: uchar(1)) << QVariant::fromValue(value: 0U) << +1;
1924 QTest::newRow(dataTag: "uchar+uint4") << QVariant::fromValue(value: uchar(1)) << QVariant::fromValue(value: 1U) << 0;
1925
1926 QTest::newRow(dataTag: "short+uint1") << QVariant::fromValue(value: short(0)) << QVariant::fromValue(value: 0U) << 0;
1927 QTest::newRow(dataTag: "short+uint2") << QVariant::fromValue(value: short(0)) << QVariant::fromValue(value: 1U) << -1;
1928 QTest::newRow(dataTag: "short+uint3") << QVariant::fromValue(value: short(1)) << QVariant::fromValue(value: 0U) << +1;
1929 QTest::newRow(dataTag: "short+uint4") << QVariant::fromValue(value: short(1)) << QVariant::fromValue(value: 1U) << 0;
1930
1931 QTest::newRow(dataTag: "ushort+uint1") << QVariant::fromValue(value: ushort(0)) << QVariant::fromValue(value: 0U) << 0;
1932 QTest::newRow(dataTag: "ushort+uint2") << QVariant::fromValue(value: ushort(0)) << QVariant::fromValue(value: 1U) << -1;
1933 QTest::newRow(dataTag: "ushort+uint3") << QVariant::fromValue(value: ushort(1)) << QVariant::fromValue(value: 0U) << +1;
1934 QTest::newRow(dataTag: "ushort+uint4") << QVariant::fromValue(value: ushort(1)) << QVariant::fromValue(value: 1U) << 0;
1935
1936 // int + qlonglong
1937 QTest::newRow(dataTag: "int+qlonglong1") << QVariant::fromValue(value: 0) << QVariant::fromValue(Q_INT64_C(0)) << 0;
1938 QTest::newRow(dataTag: "int+qlonglong2") << QVariant::fromValue(value: 1) << QVariant::fromValue(Q_INT64_C(0)) << +1;
1939 QTest::newRow(dataTag: "int+qlonglong3") << QVariant::fromValue(value: 0) << QVariant::fromValue(Q_INT64_C(1)) << -1;
1940 QTest::newRow(dataTag: "int+qlonglong4") << QVariant::fromValue(value: 1) << QVariant::fromValue(Q_INT64_C(1)) << 0;
1941 QTest::newRow(dataTag: "int+qlonglong5") << QVariant::fromValue(value: 0) << QVariant::fromValue(Q_INT64_C(-1)) << +1;
1942 QTest::newRow(dataTag: "int+qlonglong6") << QVariant::fromValue(value: -1) << QVariant::fromValue(Q_INT64_C(0)) << -1;
1943 QTest::newRow(dataTag: "int+qlonglong7") << QVariant::fromValue(value: -1) << QVariant::fromValue(Q_INT64_C(-1)) << 0;
1944
1945 // uint + qulonglong
1946 QTest::newRow(dataTag: "uint+qulonglong1") << QVariant::fromValue(value: 0U) << QVariant::fromValue(Q_UINT64_C(0)) << 0;
1947 QTest::newRow(dataTag: "uint+qulonglong2") << QVariant::fromValue(value: 1U) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
1948 QTest::newRow(dataTag: "uint+qulonglong3") << QVariant::fromValue(value: 0U) << QVariant::fromValue(Q_UINT64_C(1)) << -1;
1949 QTest::newRow(dataTag: "uint+qulonglong4") << QVariant::fromValue(value: 1U) << QVariant::fromValue(Q_UINT64_C(1)) << 0;
1950
1951 // int + uint (without sign change)
1952 QTest::newRow(dataTag: "int+uint1") << QVariant::fromValue(value: 0) << QVariant::fromValue(value: 0U) << 0;
1953 QTest::newRow(dataTag: "int+uint2") << QVariant::fromValue(value: 1) << QVariant::fromValue(value: 0U) << +1;
1954 QTest::newRow(dataTag: "int+uint3") << QVariant::fromValue(value: 0) << QVariant::fromValue(value: 1U) << -1;
1955 QTest::newRow(dataTag: "int+uint4") << QVariant::fromValue(value: 1) << QVariant::fromValue(value: 1U) << 0;
1956
1957 // uint + qlonglong
1958 QTest::newRow(dataTag: "uint+qlonglong1") << QVariant::fromValue(value: 0U) << QVariant::fromValue(Q_INT64_C(0)) << 0;
1959 QTest::newRow(dataTag: "uint+qlonglong2") << QVariant::fromValue(value: 1U) << QVariant::fromValue(Q_INT64_C(0)) << +1;
1960 QTest::newRow(dataTag: "uint+qlonglong3") << QVariant::fromValue(value: 0U) << QVariant::fromValue(Q_INT64_C(1)) << -1;
1961 QTest::newRow(dataTag: "uint+qlonglong4") << QVariant::fromValue(value: 1U) << QVariant::fromValue(Q_INT64_C(1)) << 0;
1962 QTest::newRow(dataTag: "uint+qlonglong5") << QVariant::fromValue(value: 0U) << QVariant::fromValue(Q_INT64_C(-1)) << +1;
1963
1964 // boundary conditions
1965 QTest::newRow(dataTag: "charmax+intmax") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
1966 QTest::newRow(dataTag: "charmax+uintmax") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
1967 QTest::newRow(dataTag: "scharmax+intmax") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
1968 QTest::newRow(dataTag: "scharmax+uintmax") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
1969 QTest::newRow(dataTag: "ucharmax+intmax") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
1970 QTest::newRow(dataTag: "ucharmax+uintmax") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
1971 QTest::newRow(dataTag: "shortmax+intmax") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(INT_MAX) << -1;
1972 QTest::newRow(dataTag: "shortmax+uintmax") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
1973 QTest::newRow(dataTag: "ushortmax+intmax") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(INT_MAX) << -1;
1974 QTest::newRow(dataTag: "ushortmax+uintmax") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
1975
1976 QTest::newRow(dataTag: "intmin+qlonglongmin") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(LLONG_MIN) << +1;
1977 QTest::newRow(dataTag: "intmax+uintmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
1978 QTest::newRow(dataTag: "intmax+qlonglongmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(LLONG_MAX) << -1;
1979 QTest::newRow(dataTag: "uintmax+qlonglongmax") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(LLONG_MAX) << -1;
1980 QTest::newRow(dataTag: "intmax+qulonglongmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(ULLONG_MAX) << -1;
1981 QTest::newRow(dataTag: "qlonglongmax+qulonglongmax") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(ULLONG_MAX) << -1;
1982 QTest::newRow(dataTag: "uintmax+qlonglongmin") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(LLONG_MIN) << +1;
1983
1984 // check for no sign-extension issues
1985 QTest::newRow(dataTag: "ushortmax+intzero") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(value: 0) << +1;
1986 QTest::newRow(dataTag: "ushortmax+qlonglongzero") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(Q_INT64_C(0)) << +1;
1987 QTest::newRow(dataTag: "uintmax+qlonglongzero") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(Q_INT64_C(0)) << +1;
1988
1989 // sign changes
1990 // the tests below check that a signed negative number sign-changes to a non-zero unsigned number and that
1991 // signed -1 sign-changes to unsigned maximum (all bits set, ~0). This works on two's complement machines
1992 // (all that Qt supports), and would also work on one's complement.
1993 if (std::numeric_limits<char>::is_signed) {
1994 QTest::newRow(dataTag: "signchange-char+uint") << QVariant::fromValue(value: char(-1)) << QVariant::fromValue(value: 0U) << +1;
1995 QTest::newRow(dataTag: "signchange-char+uintmax") << QVariant::fromValue(value: char(-1)) << QVariant::fromValue(UINT_MAX) << 0;
1996 QTest::newRow(dataTag: "signchange-charmin+uint") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(value: 0U) << +1;
1997 QTest::newRow(dataTag: "signchange-char+qulonglong") << QVariant::fromValue(value: char(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
1998 QTest::newRow(dataTag: "signchange-char+qulonglongmax") << QVariant::fromValue(value: char(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
1999 QTest::newRow(dataTag: "signchange-charmin+qulonglong") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2000 }
2001 QTest::newRow(dataTag: "signchange-schar+uint") << QVariant::fromValue(value: schar(-1)) << QVariant::fromValue(value: 0U) << +1;
2002 QTest::newRow(dataTag: "signchange-schar+uintmax") << QVariant::fromValue(value: schar(-1)) << QVariant::fromValue(UINT_MAX) << 0;
2003 QTest::newRow(dataTag: "signchange-scharmin+uint") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(value: 0U) << +1;
2004 QTest::newRow(dataTag: "signchange-schar+qulonglong") << QVariant::fromValue(value: schar(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2005 QTest::newRow(dataTag: "signchange-schar+qulonglongmax") << QVariant::fromValue(value: schar(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
2006 QTest::newRow(dataTag: "signchange-scharmin+qulonglong") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2007 QTest::newRow(dataTag: "signchange-short+uint") << QVariant::fromValue(value: short(-1)) << QVariant::fromValue(value: 0U) << +1;
2008 QTest::newRow(dataTag: "signchange-short+uintmax") << QVariant::fromValue(value: short(-1)) << QVariant::fromValue(UINT_MAX) << 0;
2009 QTest::newRow(dataTag: "signchange-shortmin+uint") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(value: 0U) << +1;
2010 QTest::newRow(dataTag: "signchange-short+qulonglong") << QVariant::fromValue(value: short(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2011 QTest::newRow(dataTag: "signchange-short+qulonglongmax") << QVariant::fromValue(value: short(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
2012 QTest::newRow(dataTag: "signchange-shortmin+qulonglong") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2013 QTest::newRow(dataTag: "signchange-int+uint") << QVariant::fromValue(value: -1) << QVariant::fromValue(value: 0U) << +1;
2014 QTest::newRow(dataTag: "signchange-int+uintmax") << QVariant::fromValue(value: -1) << QVariant::fromValue(UINT_MAX) << 0;
2015 QTest::newRow(dataTag: "signchange-intmin+uint") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(value: 0U) << +1;
2016 QTest::newRow(dataTag: "signchange-int+qulonglong") << QVariant::fromValue(value: -1) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2017 QTest::newRow(dataTag: "signchange-int+qulonglongmax") << QVariant::fromValue(value: -1) << QVariant::fromValue(ULLONG_MAX) << 0;
2018 QTest::newRow(dataTag: "signchange-intmin+qulonglong") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2019 // no qlonglong+uint, since that should promote to qlonglong and then the comparison is signed (tested above)
2020 QTest::newRow(dataTag: "signchange-qlonglong+qulonglong") << QVariant::fromValue(Q_INT64_C(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2021 QTest::newRow(dataTag: "signchange-qlonglong+qulonglongmax") << QVariant::fromValue(Q_INT64_C(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
2022 QTest::newRow(dataTag: "signchange-qlonglongmin+qulonglong") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
2023}
2024
2025void tst_QVariant::compareNumbers() const
2026{
2027 QFETCH(QVariant, v1);
2028 QFETCH(QVariant, v2);
2029 QFETCH(int, expected);
2030
2031 if (expected == -1) {
2032 QVERIFY(v1 < v2);
2033 QVERIFY(v1 <= v2);
2034 QVERIFY(!(v1 == v2));
2035 QVERIFY(!(v1 > v2));
2036 QVERIFY(!(v1 >= v2));
2037
2038 QVERIFY(!(v2 < v1));
2039 QVERIFY(!(v2 <= v1));
2040 QVERIFY(!(v2 == v1));
2041 QVERIFY(v2 >= v1);
2042 QVERIFY(v2 > v1);
2043 } else if (expected == 0) {
2044 QVERIFY(!(v1 < v2));
2045 QVERIFY(v1 <= v2);
2046 QCOMPARE(v1, v2);
2047 QVERIFY(!(v1 > v2));
2048 QVERIFY(v1 >= v2);
2049
2050 QVERIFY(!(v2 < v1));
2051 QVERIFY(v2 <= v1);
2052 QCOMPARE(v2, v1);
2053 QVERIFY(v2 >= v1);
2054 QVERIFY(!(v2 > v1));
2055 } else if (expected == +1) {
2056 QVERIFY(!(v1 < v2));
2057 QVERIFY(!(v1 <= v2));
2058 QVERIFY(!(v1 == v2));
2059 QVERIFY(v1 > v2);
2060 QVERIFY(v1 >= v2);
2061
2062 QVERIFY(v2 < v1);
2063 QVERIFY(v2 <= v1);
2064 QVERIFY(!(v2 == v1));
2065 QVERIFY(!(v2 >= v1));
2066 QVERIFY(!(v2 > v1));
2067 } else {
2068 // unorderable (NaN)
2069 QVERIFY(!(v1 == v2));
2070 }
2071}
2072
2073void tst_QVariant::typeName_data()
2074{
2075 QTest::addColumn<int>(name: "type");
2076 QTest::addColumn<QByteArray>(name: "res");
2077 QTest::newRow(dataTag: "0") << int(QVariant::Invalid) << QByteArray("");
2078 QTest::newRow(dataTag: "1") << int(QVariant::Map) << QByteArray("QVariantMap");
2079 QTest::newRow(dataTag: "2") << int(QVariant::List) << QByteArray("QVariantList");
2080 QTest::newRow(dataTag: "3") << int(QVariant::String) << QByteArray("QString");
2081 QTest::newRow(dataTag: "4") << int(QVariant::StringList) << QByteArray("QStringList");
2082 QTest::newRow(dataTag: "5") << int(QVariant::Font) << QByteArray("QFont");
2083 QTest::newRow(dataTag: "6") << int(QVariant::Pixmap) << QByteArray("QPixmap");
2084 QTest::newRow(dataTag: "7") << int(QVariant::Brush) << QByteArray("QBrush");
2085 QTest::newRow(dataTag: "8") << int(QVariant::Rect) << QByteArray("QRect");
2086 QTest::newRow(dataTag: "9") << int(QVariant::Size) << QByteArray("QSize");
2087 QTest::newRow(dataTag: "10") << int(QVariant::Color) << QByteArray("QColor");
2088 QTest::newRow(dataTag: "11") << int(QVariant::Palette) << QByteArray("QPalette");
2089 QTest::newRow(dataTag: "12") << int(QVariant::Point) << QByteArray("QPoint");
2090 QTest::newRow(dataTag: "13") << int(QVariant::Image) << QByteArray("QImage");
2091 QTest::newRow(dataTag: "14") << int(QVariant::Int) << QByteArray("int");
2092 QTest::newRow(dataTag: "15") << int(QVariant::UInt) << QByteArray("uint");
2093 QTest::newRow(dataTag: "16") << int(QVariant::Bool) << QByteArray("bool");
2094 QTest::newRow(dataTag: "17") << int(QVariant::Double) << QByteArray("double");
2095 QTest::newRow(dataTag: "18") << int(QMetaType::Float) << QByteArray("float");
2096 QTest::newRow(dataTag: "19") << int(QVariant::Polygon) << QByteArray("QPolygon");
2097 QTest::newRow(dataTag: "20") << int(QVariant::Region) << QByteArray("QRegion");
2098 QTest::newRow(dataTag: "21") << int(QVariant::Bitmap) << QByteArray("QBitmap");
2099 QTest::newRow(dataTag: "22") << int(QVariant::Cursor) << QByteArray("QCursor");
2100 QTest::newRow(dataTag: "23") << int(QVariant::SizePolicy) << QByteArray("QSizePolicy");
2101 QTest::newRow(dataTag: "24") << int(QVariant::Date) << QByteArray("QDate");
2102 QTest::newRow(dataTag: "25") << int(QVariant::Time) << QByteArray("QTime");
2103 QTest::newRow(dataTag: "26") << int(QVariant::DateTime) << QByteArray("QDateTime");
2104 QTest::newRow(dataTag: "27") << int(QVariant::ByteArray) << QByteArray("QByteArray");
2105 QTest::newRow(dataTag: "28") << int(QVariant::BitArray) << QByteArray("QBitArray");
2106 QTest::newRow(dataTag: "29") << int(QVariant::KeySequence) << QByteArray("QKeySequence");
2107 QTest::newRow(dataTag: "30") << int(QVariant::Pen) << QByteArray("QPen");
2108 QTest::newRow(dataTag: "31") << int(QVariant::LongLong) << QByteArray("qlonglong");
2109 QTest::newRow(dataTag: "32") << int(QVariant::ULongLong) << QByteArray("qulonglong");
2110 QTest::newRow(dataTag: "33") << int(QVariant::Char) << QByteArray("QChar");
2111 QTest::newRow(dataTag: "34") << int(QVariant::Url) << QByteArray("QUrl");
2112 QTest::newRow(dataTag: "35") << int(QVariant::TextLength) << QByteArray("QTextLength");
2113 QTest::newRow(dataTag: "36") << int(QVariant::TextFormat) << QByteArray("QTextFormat");
2114 QTest::newRow(dataTag: "37") << int(QVariant::Locale) << QByteArray("QLocale");
2115 QTest::newRow(dataTag: "38") << int(QVariant::LineF) << QByteArray("QLineF");
2116 QTest::newRow(dataTag: "39") << int(QVariant::RectF) << QByteArray("QRectF");
2117 QTest::newRow(dataTag: "40") << int(QVariant::PointF) << QByteArray("QPointF");
2118 QTest::newRow(dataTag: "41") << int(QVariant::RegExp) << QByteArray("QRegExp");
2119 QTest::newRow(dataTag: "43") << int(QVariant::Matrix) << QByteArray("QMatrix");
2120 QTest::newRow(dataTag: "44") << int(QVariant::Transform) << QByteArray("QTransform");
2121 QTest::newRow(dataTag: "45") << int(QVariant::Hash) << QByteArray("QVariantHash");
2122 QTest::newRow(dataTag: "46") << int(QVariant::Matrix4x4) << QByteArray("QMatrix4x4");
2123 QTest::newRow(dataTag: "47") << int(QVariant::Vector2D) << QByteArray("QVector2D");
2124 QTest::newRow(dataTag: "48") << int(QVariant::Vector3D) << QByteArray("QVector3D");
2125 QTest::newRow(dataTag: "49") << int(QVariant::Vector4D) << QByteArray("QVector4D");
2126 QTest::newRow(dataTag: "50") << int(QVariant::Quaternion) << QByteArray("QQuaternion");
2127 QTest::newRow(dataTag: "51") << int(QVariant::RegularExpression) << QByteArray("QRegularExpression");
2128}
2129
2130void tst_QVariant::typeName()
2131{
2132 QFETCH( int, type );
2133 QFETCH( QByteArray, res );
2134 QCOMPARE(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type)),
2135 QString::fromLatin1(res.constData()));
2136}
2137
2138// test nameToType as well
2139void tst_QVariant::typeToName()
2140{
2141 QVariant v;
2142 QCOMPARE( QVariant::typeToName( v.type() ), (const char*)0 ); // Invalid
2143 // assumes that QVariant::Type contains consecutive values
2144
2145 int max = QVariant::LastGuiType;
2146 for ( int t = 1; t <= max; t++ ) {
2147 const char *n = QVariant::typeToName( typeId: (QVariant::Type)t );
2148 if (n)
2149 QCOMPARE( int(QVariant::nameToType( n )), t );
2150
2151 }
2152 QCOMPARE(QVariant::typeToName(QVariant::Int), "int");
2153 // not documented but we return 0 if the type is out of range
2154 // by testing this we catch cases where QVariant is extended
2155 // but type_map is not updated accordingly
2156 QCOMPARE( QVariant::typeToName( QVariant::Type(max+1) ), (char*)0 );
2157 // invalid type names
2158 QVERIFY( QVariant::nameToType( 0 ) == QVariant::Invalid );
2159 QVERIFY( QVariant::nameToType( "" ) == QVariant::Invalid );
2160 QVERIFY( QVariant::nameToType( "foo" ) == QVariant::Invalid );
2161
2162 QCOMPARE(QVariant::nameToType("UserType"), QVariant::Invalid);
2163
2164 // We don't support these old (Qt3) types anymore.
2165 QCOMPARE(QVariant::nameToType("QIconSet"), QVariant::Invalid);
2166 QCOMPARE(QVariant::nameToType("Q3CString"), QVariant::Invalid);
2167 QCOMPARE(QVariant::nameToType("Q_LLONG"), QVariant::Invalid);
2168 QCOMPARE(QVariant::nameToType("Q_ULLONG"), QVariant::Invalid);
2169}
2170
2171void tst_QVariant::streamInvalidVariant()
2172{
2173 int writeX = 1;
2174 int writeY = 2;
2175 int readX;
2176 int readY;
2177 QVariant writeVariant;
2178 QVariant readVariant;
2179
2180 QVERIFY( writeVariant.type() == QVariant::Invalid );
2181
2182 QByteArray data;
2183 QDataStream writeStream( &data, QIODevice::WriteOnly );
2184 writeStream << writeX << writeVariant << writeY;
2185
2186 QDataStream readStream( &data, QIODevice::ReadOnly );
2187 readStream >> readX >> readVariant >> readY;
2188
2189 QVERIFY( readX == writeX );
2190 // Two invalid QVariant's aren't necessarily the same, so == will
2191 // return false if one is invalid, so check the type() instead
2192 QVERIFY( readVariant.type() == QVariant::Invalid );
2193 QVERIFY( readY == writeY );
2194}
2195
2196static int instanceCount = 0;
2197
2198struct MyType
2199{
2200 MyType(int n = 0, const char *t=0): number(n), text(t)
2201 {
2202 ++instanceCount;
2203 }
2204 MyType(const MyType &other)
2205 : number(other.number), text(other.text)
2206 {
2207 ++instanceCount;
2208 }
2209 ~MyType()
2210 {
2211 --instanceCount;
2212 }
2213 int number;
2214 const char *text;
2215};
2216
2217Q_DECLARE_METATYPE(MyType)
2218Q_DECLARE_METATYPE(MyType*)
2219
2220void tst_QVariant::userType()
2221{
2222 {
2223 MyType data(1, "eins");
2224 MyType data2(2, "zwei");
2225
2226 {
2227 QVariant userVar;
2228 userVar.setValue(data);
2229
2230 QCOMPARE(userVar.type(), QVariant::UserType);
2231 QCOMPARE(userVar.userType(), qMetaTypeId<MyType>());
2232 QCOMPARE(userVar.typeName(), "MyType");
2233 QVERIFY(!userVar.isNull());
2234 QVERIFY(!userVar.canConvert(QVariant::String));
2235
2236 QVariant userVar2(userVar);
2237 QCOMPARE(userVar, userVar2);
2238
2239 userVar2.setValue(data2);
2240 QVERIFY(userVar != userVar2);
2241
2242 const MyType *varData = static_cast<const MyType *>(userVar.constData());
2243 QVERIFY(varData);
2244 QCOMPARE(varData->number, data.number);
2245 QCOMPARE(varData->text, data.text);
2246
2247 QVariant userVar3;
2248 userVar3.setValue(data2);
2249
2250 userVar3 = userVar2;
2251 QCOMPARE(userVar2, userVar3);
2252 }
2253 // At this point all QVariants got destroyed but we have 2 MyType instances.
2254 QCOMPARE(instanceCount, 2);
2255 {
2256 QVariant userVar;
2257 userVar.setValue(&data);
2258
2259 QCOMPARE(userVar.type(), QVariant::UserType);
2260 QCOMPARE(userVar.userType(), qMetaTypeId<MyType*>());
2261 QCOMPARE(userVar.typeName(), "MyType*");
2262 QVERIFY(!userVar.isNull());
2263 QVERIFY(!userVar.canConvert(QVariant::String));
2264
2265 QVariant userVar2(userVar);
2266 QCOMPARE(userVar, userVar2);
2267
2268 userVar2.setValue(&data2);
2269 QVERIFY(userVar != userVar2);
2270
2271 MyType * const*varData = reinterpret_cast<MyType *const *>(userVar.constData());
2272 QVERIFY(varData);
2273 QCOMPARE(*varData, &data);
2274
2275 QVariant userVar3;
2276 userVar3.setValue(&data2);
2277
2278 /* This check is correct now. userVar2 contains a pointer to data2 and so
2279 * does userVar3. */
2280 QCOMPARE(userVar2, userVar3);
2281
2282 userVar3 = userVar2;
2283 QCOMPARE(userVar2, userVar3);
2284 }
2285
2286 QCOMPARE(instanceCount, 2);
2287 QVariant myCarrier;
2288 myCarrier.setValue(data);
2289 QCOMPARE(instanceCount, 3);
2290 {
2291 QVariant second = myCarrier;
2292 QCOMPARE(instanceCount, 3);
2293 second.detach();
2294 QCOMPARE(instanceCount, 4);
2295 }
2296 QCOMPARE(instanceCount, 3);
2297
2298 MyType data3(0, "null");
2299 data3 = qvariant_cast<MyType>(v: myCarrier);
2300 QCOMPARE(data3.number, 1);
2301 QCOMPARE(data3.text, (const char *)"eins");
2302#ifndef Q_CC_SUN
2303 QCOMPARE(instanceCount, 4);
2304#endif
2305
2306 }
2307
2308 {
2309 const MyType data(3, "drei");
2310 QVariant myCarrier;
2311
2312 myCarrier.setValue(data);
2313 QCOMPARE(myCarrier.typeName(), "MyType");
2314
2315 const MyType data2 = qvariant_cast<MyType>(v: myCarrier);
2316 QCOMPARE(data2.number, 3);
2317 QCOMPARE(data2.text, (const char *)"drei");
2318 }
2319
2320 {
2321 short s = 42;
2322 QVariant myCarrier;
2323
2324 myCarrier.setValue(s);
2325 QCOMPARE((int)qvariant_cast<short>(myCarrier), 42);
2326 }
2327
2328 {
2329 qlonglong ll = Q_INT64_C(42);
2330 QVariant myCarrier;
2331
2332 myCarrier.setValue(ll);
2333 QCOMPARE(qvariant_cast<int>(myCarrier), 42);
2334 }
2335
2336 // At this point all QVariants got destroyed and MyType objects too.
2337 QCOMPARE(instanceCount, 0);
2338}
2339
2340struct MyTypePOD
2341{
2342 int a;
2343 int b;
2344};
2345Q_DECLARE_METATYPE(MyTypePOD)
2346
2347void tst_QVariant::podUserType()
2348{
2349 MyTypePOD pod;
2350 pod.a = 10;
2351 pod.b = 20;
2352
2353 QVariant pod_as_variant = QVariant::fromValue(value: pod);
2354 MyTypePOD pod2 = qvariant_cast<MyTypePOD>(v: pod_as_variant);
2355
2356 QCOMPARE(pod.a, pod2.a);
2357 QCOMPARE(pod.b, pod2.b);
2358
2359 pod_as_variant.setValue(pod);
2360 pod2 = qvariant_cast<MyTypePOD>(v: pod_as_variant);
2361
2362 QCOMPARE(pod.a, pod2.a);
2363 QCOMPARE(pod.b, pod2.b);
2364}
2365
2366void tst_QVariant::basicUserType()
2367{
2368 QVariant v;
2369 {
2370 int i = 7;
2371 v = QVariant(QMetaType::Int, &i);
2372 }
2373 QCOMPARE(v.type(), QVariant::Int);
2374 QCOMPARE(v.toInt(), 7);
2375
2376 {
2377 QString s("foo");
2378 v = QVariant(QMetaType::QString, &s);
2379 }
2380 QCOMPARE(v.type(), QVariant::String);
2381 QCOMPARE(v.toString(), QString("foo"));
2382
2383 {
2384 double d = 4.4;
2385 v = QVariant(QMetaType::Double, &d);
2386 }
2387 QCOMPARE(v.type(), QVariant::Double);
2388 QCOMPARE(v.toDouble(), 4.4);
2389
2390 {
2391 float f = 4.5f;
2392 v = QVariant(QMetaType::Float, &f);
2393 }
2394 QCOMPARE(v.userType(), int(QMetaType::Float));
2395 QCOMPARE(v.toDouble(), 4.5);
2396
2397 {
2398 QByteArray ba("bar");
2399 v = QVariant(QMetaType::QByteArray, &ba);
2400 }
2401 QCOMPARE(v.type(), QVariant::ByteArray);
2402 QCOMPARE(v.toByteArray(), QByteArray("bar"));
2403}
2404
2405void tst_QVariant::data()
2406{
2407 QVariant v;
2408
2409 QVariant i = 1;
2410 QVariant d = 1.12;
2411 QVariant f = 1.12f;
2412 QVariant ll = (qlonglong)2;
2413 QVariant ull = (qulonglong)3;
2414 QVariant s(QString("hallo"));
2415 QVariant r(QRect(1,2,3,4));
2416
2417 v = i;
2418 QVERIFY(v.data());
2419 QCOMPARE(*static_cast<int *>(v.data()), i.toInt());
2420
2421 v = d;
2422 QVERIFY(v.data());
2423 QCOMPARE(*static_cast<double *>(v.data()), d.toDouble());
2424
2425 v = f;
2426 QVERIFY(v.data());
2427 QCOMPARE(*static_cast<float *>(v.data()), qvariant_cast<float>(v));
2428
2429 v = ll;
2430 QVERIFY(v.data());
2431 QCOMPARE(*static_cast<qlonglong *>(v.data()), ll.toLongLong());
2432
2433 v = ull;
2434 QVERIFY(v.data());
2435 QCOMPARE(*static_cast<qulonglong *>(v.data()), ull.toULongLong());
2436
2437 v = s;
2438 QVERIFY(v.data());
2439 QCOMPARE(*static_cast<QString *>(v.data()), s.toString());
2440
2441 v = r;
2442 QVERIFY(v.data());
2443 QCOMPARE(*static_cast<QRect *>(v.data()), r.toRect());
2444}
2445
2446void tst_QVariant::constData()
2447{
2448 QVariant v;
2449
2450 int i = 1;
2451 double d = 1.12;
2452 float f = 1.12f;
2453 qlonglong ll = 2;
2454 qulonglong ull = 3;
2455 QString s("hallo");
2456 QRect r(1,2,3,4);
2457
2458 v = QVariant(i);
2459 QVERIFY(v.constData());
2460 QCOMPARE(*static_cast<const int *>(v.constData()), i);
2461
2462 v = QVariant(d);
2463 QVERIFY(v.constData());
2464 QCOMPARE(*static_cast<const double *>(v.constData()), d);
2465
2466 v = QVariant(f);
2467 QVERIFY(v.constData());
2468 QCOMPARE(*static_cast<const float *>(v.constData()), f);
2469
2470 v = QVariant(ll);
2471 QVERIFY(v.constData());
2472 QCOMPARE(*static_cast<const qlonglong *>(v.constData()), ll);
2473
2474 v = QVariant(ull);
2475 QVERIFY(v.constData());
2476 QCOMPARE(*static_cast<const qulonglong *>(v.constData()), ull);
2477
2478 v = QVariant(s);
2479 QVERIFY(v.constData());
2480 QCOMPARE(*static_cast<const QString *>(v.constData()), s);
2481
2482 v = QVariant(r);
2483 QVERIFY(v.constData());
2484 QCOMPARE(*static_cast<const QRect *>(v.constData()), r);
2485}
2486
2487struct Foo
2488{
2489 Foo(): i(0) {}
2490 int i;
2491};
2492
2493Q_DECLARE_METATYPE(Foo)
2494
2495void tst_QVariant::variant_to()
2496{
2497 QVariant v1(4.2);
2498 QVariant v2(5);
2499
2500 QVariant v3;
2501 QVariant v4;
2502
2503 QStringList sl;
2504 sl << QLatin1String("blah");
2505
2506 v3.setValue(sl);
2507
2508 Foo foo;
2509 foo.i = 42;
2510
2511 v4.setValue(foo);
2512
2513 QCOMPARE(qvariant_cast<double>(v1), 4.2);
2514 QCOMPARE(qvariant_cast<float>(v1), 4.2f);
2515 QCOMPARE(qvariant_cast<int>(v2), 5);
2516 QCOMPARE(qvariant_cast<QStringList>(v3), sl);
2517 QCOMPARE(qvariant_cast<QString>(v3), QString::fromLatin1("blah"));
2518
2519 QCOMPARE(qvariant_cast<Foo>(v4).i, 42);
2520
2521 QVariant v5;
2522 QCOMPARE(qvariant_cast<Foo>(v5).i, 0);
2523
2524 QCOMPARE(qvariant_cast<int>(v1), 4);
2525
2526 QVariant n = QVariant::fromValue<short>(value: 42);
2527 QCOMPARE(qvariant_cast<int>(n), 42);
2528 QCOMPARE(qvariant_cast<uint>(n), 42u);
2529 QCOMPARE(qvariant_cast<double>(n), 42.0);
2530 QCOMPARE(qvariant_cast<float>(n), 42.f);
2531 QCOMPARE(qvariant_cast<short>(n), short(42));
2532 QCOMPARE(qvariant_cast<ushort>(n), ushort(42));
2533
2534 n = QVariant::fromValue(value: 43l);
2535 QCOMPARE(qvariant_cast<int>(n), 43);
2536 QCOMPARE(qvariant_cast<uint>(n), 43u);
2537 QCOMPARE(qvariant_cast<double>(n), 43.0);
2538 QCOMPARE(qvariant_cast<float>(n), 43.f);
2539 QCOMPARE(qvariant_cast<long>(n), 43l);
2540
2541 n = QLatin1String("44");
2542 QCOMPARE(qvariant_cast<int>(n), 44);
2543 QCOMPARE(qvariant_cast<ulong>(n), 44ul);
2544 QCOMPARE(qvariant_cast<float>(n), 44.0f);
2545
2546 QCOMPARE(QVariant::fromValue(0.25f).toDouble(), 0.25);
2547}
2548
2549struct Blah { int i; };
2550
2551QDataStream& operator>>(QDataStream& s, Blah& c)
2552{ return (s >> c.i); }
2553
2554QDataStream& operator<<(QDataStream& s, const Blah& c)
2555{ return (s << c.i); }
2556
2557void tst_QVariant::saveLoadCustomTypes()
2558{
2559 QByteArray data;
2560
2561 Blah i = { .i: 42 };
2562 int tp = qRegisterMetaType<Blah>(typeName: "Blah");
2563 QVariant v = QVariant(tp, &i);
2564
2565 qRegisterMetaTypeStreamOperators<Blah>(typeName: "Blah");
2566
2567 QCOMPARE(v.userType(), tp);
2568 QCOMPARE(v.type(), QVariant::UserType);
2569 {
2570 QDataStream stream(&data, QIODevice::WriteOnly);
2571 stream << v;
2572 }
2573
2574 v = QVariant();
2575
2576 {
2577 QDataStream stream(data);
2578 stream >> v;
2579 }
2580
2581 QCOMPARE(int(v.userType()), QMetaType::type("Blah"));
2582 int value = *(int*)v.constData();
2583 QCOMPARE(value, 42);
2584}
2585
2586void tst_QVariant::url()
2587{
2588 QString str("http://qt-project.org");
2589 QUrl url(str);
2590
2591 QVariant v(url); //built with a QUrl
2592
2593 QVariant v2 = v;
2594
2595 QVariant v3(str); //built with a QString
2596
2597 QCOMPARE(v2.toUrl(), url);
2598 QVERIFY(v3.canConvert<QUrl>());
2599 QCOMPARE(v2.toUrl(), v3.toUrl());
2600
2601 QVERIFY(v2.canConvert<QString>());
2602 QCOMPARE(v2.toString(), str);
2603 QCOMPARE(v3.toString(), str);
2604}
2605
2606void tst_QVariant::variantMap()
2607{
2608 QMap<QString, QVariant> map;
2609 map["test"] = 42;
2610
2611 QVariant v = map;
2612 QVariantMap map2 = qvariant_cast<QVariantMap>(v);
2613 QCOMPARE(map2.value("test").toInt(), 42);
2614 QCOMPARE(map2, map);
2615
2616 map2 = v.toMap();
2617 QCOMPARE(map2.value("test").toInt(), 42);
2618 QCOMPARE(map2, map);
2619
2620 QVariant v2 = QVariant(QMetaType::type(typeName: "QVariantMap"), &map);
2621 QCOMPARE(qvariant_cast<QVariantMap>(v2).value("test").toInt(), 42);
2622
2623 QVariant v3 = QVariant(QMetaType::type(typeName: "QMap<QString, QVariant>"), &map);
2624 QCOMPARE(qvariant_cast<QVariantMap>(v3).value("test").toInt(), 42);
2625
2626 QCOMPARE(v, QVariant(v.toHash()));
2627
2628 // multi-keys
2629 map.insertMulti(key: "test", value: 47);
2630 v = map;
2631 map2 = qvariant_cast<QVariantMap>(v);
2632 QCOMPARE(map2, map);
2633 map2 = v.toMap();
2634 QCOMPARE(map2, map);
2635
2636 QCOMPARE(v, QVariant(v.toHash()));
2637}
2638
2639void tst_QVariant::variantHash()
2640{
2641 QHash<QString, QVariant> hash;
2642 hash["test"] = 42;
2643
2644 QVariant v = hash;
2645 QVariantHash hash2 = qvariant_cast<QVariantHash>(v);
2646 QCOMPARE(hash2.value("test").toInt(), 42);
2647 QCOMPARE(hash2, hash);
2648
2649 hash2 = v.toHash();
2650 QCOMPARE(hash2.value("test").toInt(), 42);
2651 QCOMPARE(hash2, hash);
2652
2653 QVariant v2 = QVariant(QMetaType::type(typeName: "QVariantHash"), &hash);
2654 QCOMPARE(qvariant_cast<QVariantHash>(v2).value("test").toInt(), 42);
2655
2656 QVariant v3 = QVariant(QMetaType::type(typeName: "QHash<QString, QVariant>"), &hash);
2657 QCOMPARE(qvariant_cast<QVariantHash>(v3).value("test").toInt(), 42);
2658
2659 QCOMPARE(v, QVariant(v.toMap()));
2660
2661 // multi-keys
2662 hash.insertMulti(key: "test", value: 47);
2663 v = hash;
2664 hash2 = qvariant_cast<QVariantHash>(v);
2665 QCOMPARE(hash2, hash);
2666 hash2 = v.toHash();
2667 QCOMPARE(hash2, hash);
2668
2669 QCOMPARE(v, QVariant(v.toMap()));
2670}
2671
2672class CustomQObject : public QObject {
2673 Q_OBJECT
2674public:
2675 CustomQObject(QObject *parent = 0) : QObject(parent) {}
2676};
2677Q_DECLARE_METATYPE(CustomQObject*)
2678
2679class CustomNonQObject { };
2680Q_DECLARE_METATYPE(CustomNonQObject)
2681Q_DECLARE_METATYPE(CustomNonQObject*)
2682
2683void tst_QVariant::cleanupTestCase()
2684{
2685 delete customNonQObjectPointer;
2686 qDeleteAll(c: objectPointerTestData);
2687}
2688
2689void tst_QVariant::qvariant_cast_QObject_data()
2690{
2691 QTest::addColumn<QVariant>(name: "data");
2692 QTest::addColumn<bool>(name: "success");
2693 QTest::addColumn<bool>(name: "isNull");
2694 QObject *obj = new QObject;
2695 obj->setObjectName(QString::fromLatin1(str: "Hello"));
2696 QTest::newRow(dataTag: "from QObject") << QVariant(QMetaType::QObjectStar, &obj) << true << false;
2697 QTest::newRow(dataTag: "from QObject2") << QVariant::fromValue(value: obj) << true << false;
2698 QTest::newRow(dataTag: "from String") << QVariant(QLatin1String("1, 2, 3")) << false << false;
2699 QTest::newRow(dataTag: "from int") << QVariant((int) 123) << false << false;
2700 CustomQObject *customObject = new CustomQObject(this);
2701 customObject->setObjectName(QString::fromLatin1(str: "Hello"));
2702 QTest::newRow(dataTag: "from Derived QObject") << QVariant::fromValue(value: customObject) << true << false;
2703 QTest::newRow(dataTag: "from custom Object") << QVariant::fromValue(value: CustomNonQObject()) << false << false;
2704
2705 // Deleted in cleanupTestCase.
2706 customNonQObjectPointer = new CustomNonQObject;
2707 QTest::newRow(dataTag: "from custom ObjectStar") << QVariant::fromValue(value: customNonQObjectPointer) << false << false;
2708
2709 // Deleted in cleanupTestCase.
2710 objectPointerTestData.push_back(t: obj);
2711 objectPointerTestData.push_back(t: customObject);
2712
2713 QTest::newRow(dataTag: "null QObject") << QVariant::fromValue<QObject*>(value: 0) << true << true;
2714 QTest::newRow(dataTag: "null derived QObject") << QVariant::fromValue<CustomQObject*>(value: 0) << true << true;
2715 QTest::newRow(dataTag: "null custom object") << QVariant::fromValue<CustomNonQObject*>(value: 0) << false << true;
2716 QTest::newRow(dataTag: "zero int") << QVariant::fromValue<int>(value: 0) << false << false;
2717}
2718
2719void tst_QVariant::qvariant_cast_QObject()
2720{
2721 QFETCH(QVariant, data);
2722 QFETCH(bool, success);
2723 QFETCH(bool, isNull);
2724
2725 QObject *o = qvariant_cast<QObject *>(v: data);
2726 QCOMPARE(o != 0, success && !isNull);
2727 if (success) {
2728 if (!isNull)
2729 QCOMPARE(o->objectName(), QString::fromLatin1("Hello"));
2730 QVERIFY(data.canConvert<QObject*>());
2731 QVERIFY(data.canConvert(QMetaType::QObjectStar));
2732 QVERIFY(data.canConvert(::qMetaTypeId<QObject*>()));
2733 QCOMPARE(data.value<QObject*>() == 0, isNull);
2734 QCOMPARE(data.isNull(), isNull);
2735 QVERIFY(data.convert(QMetaType::QObjectStar));
2736 QCOMPARE(data.userType(), int(QMetaType::QObjectStar));
2737 } else {
2738 QVERIFY(!data.canConvert<QObject*>());
2739 QVERIFY(!data.canConvert(QMetaType::QObjectStar));
2740 QVERIFY(!data.canConvert(::qMetaTypeId<QObject*>()));
2741 QCOMPARE(data.isNull(), isNull);
2742 QVERIFY(!data.value<QObject*>());
2743 QVERIFY(!data.convert(QMetaType::QObjectStar));
2744 QVERIFY(data.userType() != QMetaType::QObjectStar);
2745 }
2746}
2747
2748class CustomQObjectDerived : public CustomQObject {
2749 Q_OBJECT
2750public:
2751 CustomQObjectDerived(QObject *parent = 0) : CustomQObject(parent) {}
2752};
2753Q_DECLARE_METATYPE(CustomQObjectDerived*)
2754
2755class CustomQObjectDerivedNoMetaType : public CustomQObject {
2756 Q_OBJECT
2757public:
2758 CustomQObjectDerivedNoMetaType(QObject *parent = 0) : CustomQObject(parent) {}
2759};
2760
2761void tst_QVariant::qvariant_cast_QObject_derived()
2762{
2763 {
2764 CustomQObjectDerivedNoMetaType *object = new CustomQObjectDerivedNoMetaType(this);
2765 QVariant data = QVariant::fromValue(value: object);
2766 QCOMPARE(data.userType(), qMetaTypeId<CustomQObjectDerivedNoMetaType*>());
2767 QCOMPARE(data.value<QObject *>(), object);
2768 QCOMPARE(data.value<CustomQObjectDerivedNoMetaType *>(), object);
2769 QCOMPARE(data.value<CustomQObject *>(), object);
2770 }
2771 {
2772 CustomQObjectDerived *object = new CustomQObjectDerived(this);
2773 QVariant data = QVariant::fromValue(value: object);
2774
2775 QCOMPARE(data.userType(), qMetaTypeId<CustomQObjectDerived*>());
2776
2777 QCOMPARE(data.value<QObject *>(), object);
2778 QCOMPARE(data.value<CustomQObjectDerived *>(), object);
2779 QCOMPARE(data.value<CustomQObject *>(), object);
2780 }
2781 {
2782 QObject *object = new CustomQObjectDerivedNoMetaType(this);
2783 QVariant data = QVariant::fromValue(value: object);
2784 QVERIFY(data.canConvert<CustomQObjectDerivedNoMetaType*>());
2785 QVERIFY(data.convert(qMetaTypeId<CustomQObjectDerivedNoMetaType*>()));
2786 QCOMPARE(data.value<CustomQObjectDerivedNoMetaType*>(), object);
2787 QCOMPARE(data.isNull(), false);
2788 }
2789}
2790
2791struct QObjectWrapper
2792{
2793 explicit QObjectWrapper(QObject *o = 0) : obj(o) {}
2794
2795 QObject* getObject() const {
2796 return obj;
2797 }
2798private:
2799 QObject *obj;
2800};
2801
2802Q_DECLARE_METATYPE(QObjectWrapper)
2803
2804struct Converter
2805{
2806 Converter() {}
2807
2808 QObject* operator()(const QObjectWrapper &f) const
2809 {
2810 return f.getObject();
2811 }
2812};
2813
2814namespace MyNS {
2815
2816template<typename T>
2817class SmartPointer
2818{
2819 T* pointer;
2820public:
2821 typedef T element_type;
2822 explicit SmartPointer(T *t = 0)
2823 : pointer(t)
2824 {
2825 }
2826
2827 T* operator->() const { return pointer; }
2828};
2829
2830template<typename T>
2831struct SequentialContainer
2832{
2833 typedef T value_type;
2834 typedef const T* const_iterator;
2835 T t;
2836 const_iterator begin() const { return &t; }
2837 const_iterator end() const { return &t + 1; }
2838};
2839
2840template<typename T, typename U>
2841struct AssociativeContainer : public std::map<T, U>
2842{
2843};
2844
2845}
2846
2847Q_DECLARE_SMART_POINTER_METATYPE(MyNS::SmartPointer)
2848
2849Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(MyNS::SequentialContainer)
2850Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(MyNS::AssociativeContainer)
2851
2852// Test that explicit declaration does not degrade features.
2853Q_DECLARE_METATYPE(MyNS::SmartPointer<int>)
2854Q_DECLARE_METATYPE(MyNS::SmartPointer<QIODevice>)
2855Q_DECLARE_METATYPE(QSharedPointer<QIODevice>)
2856
2857void tst_QVariant::qvariant_cast_QObject_wrapper()
2858{
2859 QMetaType::registerConverter<QObjectWrapper, QObject*>(function: &QObjectWrapper::getObject);
2860
2861 CustomQObjectDerived *object = new CustomQObjectDerived(this);
2862 QObjectWrapper wrapper(object);
2863 QVariant v = QVariant::fromValue(value: wrapper);
2864 QCOMPARE(v.value<QObject*>(), object);
2865 v.convert(targetTypeId: qMetaTypeId<QObject*>());
2866 QCOMPARE(v.value<QObject*>(), object);
2867
2868 MyNS::SequentialContainer<int> sc;
2869 sc.t = 47;
2870 MyNS::AssociativeContainer<int, short> ac;
2871
2872 QVariant::fromValue(value: sc);
2873 QVariant::fromValue(value: ac);
2874
2875 {
2876 QFile *f = new QFile(this);
2877 MyNS::SmartPointer<QFile> sp(f);
2878 QVariant spVar = QVariant::fromValue(value: sp);
2879 QVERIFY(spVar.canConvert<QObject*>());
2880 QCOMPARE(f, spVar.value<QObject*>());
2881 }
2882 {
2883 QFile *f = new QFile(this);
2884 QPointer<QFile> sp(f);
2885 QVariant spVar = QVariant::fromValue(value: sp);
2886 QVERIFY(spVar.canConvert<QObject*>());
2887 QCOMPARE(f, spVar.value<QObject*>());
2888 }
2889#if QT_DEPRECATED_SINCE(5, 0)
2890 {
2891 QFile *f = new QFile(this);
2892QT_WARNING_PUSH
2893QT_WARNING_DISABLE_DEPRECATED
2894 QWeakPointer<QFile> sp(f);
2895QT_WARNING_POP
2896 QVariant spVar = QVariant::fromValue(value: sp);
2897 QVERIFY(spVar.canConvert<QObject*>());
2898 QCOMPARE(f, spVar.value<QObject*>());
2899 }
2900#endif
2901 {
2902 QFile *f = new QFile(this);
2903 QSharedPointer<QObject> sp(f);
2904 QWeakPointer<QObject> wp = sp;
2905 QVariant wpVar = QVariant::fromValue(value: wp);
2906 QVERIFY(wpVar.canConvert<QObject*>());
2907 QCOMPARE(f, wpVar.value<QObject*>());
2908 }
2909 {
2910 QFile *f = new QFile(this);
2911 QSharedPointer<QFile> sp(f);
2912 QWeakPointer<QFile> wp = sp.toWeakRef();
2913 QVariant wpVar = QVariant::fromValue(value: wp);
2914 QVERIFY(wpVar.canConvert<QObject*>());
2915 QCOMPARE(f, wpVar.value<QObject*>());
2916 }
2917 {
2918 QFile *f = new QFile(this);
2919 QSharedPointer<QFile> sp(f);
2920 QVariant spVar = QVariant::fromValue(value: sp);
2921 QVERIFY(spVar.canConvert<QObject*>());
2922 QCOMPARE(f, spVar.value<QObject*>());
2923 }
2924 {
2925 QIODevice *f = new QFile(this);
2926 MyNS::SmartPointer<QIODevice> sp(f);
2927 QVariant spVar = QVariant::fromValue(value: sp);
2928 QVERIFY(spVar.canConvert<QObject*>());
2929 QCOMPARE(f, spVar.value<QObject*>());
2930 }
2931 {
2932 QIODevice *f = new QFile(this);
2933 QSharedPointer<QIODevice> sp(f);
2934 QVariant spVar = QVariant::fromValue(value: sp);
2935 QVERIFY(spVar.canConvert<QObject*>());
2936 QCOMPARE(f, spVar.value<QObject*>());
2937 }
2938
2939 // Compile tests:
2940 qRegisterMetaType<MyNS::SmartPointer<int> >();
2941 // Not declared as a metatype:
2942 qRegisterMetaType<MyNS::SmartPointer<double> >(typeName: "MyNS::SmartPointer<double>");
2943}
2944
2945void tst_QVariant::qvariant_cast_QSharedPointerQObject()
2946{
2947 // ensure no problems between this form and the auto-registering in QVariant::fromValue
2948 qRegisterMetaType<QSharedPointer<QObject> >(typeName: "QSharedPointer<QObject>");
2949
2950 QObject *rawptr = new QObject;
2951 QSharedPointer<QObject> strong(rawptr);
2952 QWeakPointer<QObject> weak(strong);
2953 QPointer<QObject> qptr(rawptr);
2954
2955 QVariant v = QVariant::fromValue(value: strong);
2956 QCOMPARE(v.value<QSharedPointer<QObject> >(), strong);
2957
2958 // clear our QSP; the copy inside the variant should keep the object alive
2959 strong.clear();
2960
2961 // check that the object didn't get deleted
2962 QVERIFY(!weak.isNull());
2963 QVERIFY(!qptr.isNull());
2964
2965 strong = qvariant_cast<QSharedPointer<QObject> >(v);
2966 QCOMPARE(strong.data(), rawptr);
2967 QVERIFY(strong == weak);
2968
2969 // now really delete the object and verify
2970 strong.clear();
2971 v.clear();
2972 QVERIFY(weak.isNull());
2973 QVERIFY(qptr.isNull());
2974
2975 // compile test:
2976 // QVariant::fromValue has already called this function
2977 qRegisterMetaType<QSharedPointer<QObject> >();
2978}
2979
2980void tst_QVariant::convertToQUint8() const
2981{
2982 /* qint8. */
2983 {
2984 const qint8 anInt = 32;
2985
2986 /* QVariant(int) gets invoked here so the QVariant has nothing with qint8 to do.
2987 * It's of type QVariant::Int. */
2988 const QVariant v0 = anInt;
2989
2990 QVERIFY(v0.canConvert<qint8>());
2991 QCOMPARE(int(qvariant_cast<qint8>(v0)), 32);
2992 QCOMPARE(int(v0.toInt()), 32);
2993 QCOMPARE(v0.toString(), QString("32"));
2994
2995 QCOMPARE(int(qvariant_cast<qlonglong>(v0)), 32);
2996 QCOMPARE(int(qvariant_cast<char>(v0)), 32);
2997 QCOMPARE(int(qvariant_cast<short>(v0)), 32);
2998 QCOMPARE(int(qvariant_cast<long>(v0)), 32);
2999 QCOMPARE(int(qvariant_cast<float>(v0)), 32);
3000 QCOMPARE(int(qvariant_cast<double>(v0)), 32);
3001 }
3002
3003 /* quint8. */
3004 {
3005 const quint8 anInt = 32;
3006 const QVariant v0 = anInt;
3007
3008 QVERIFY(v0.canConvert<quint8>());
3009 QCOMPARE(int(qvariant_cast<quint8>(v0)), 32);
3010 QCOMPARE(int(v0.toUInt()), 32);
3011 QCOMPARE(v0.toString(), QString("32"));
3012 }
3013
3014 /* qint16. */
3015 {
3016 const qint16 anInt = 32;
3017 const QVariant v0 = anInt;
3018
3019 QVERIFY(v0.canConvert<qint16>());
3020 QCOMPARE(int(qvariant_cast<qint16>(v0)), 32);
3021 QCOMPARE(int(v0.toInt()), 32);
3022 QCOMPARE(v0.toString(), QString("32"));
3023 }
3024
3025 /* quint16. */
3026 {
3027 const quint16 anInt = 32;
3028 const QVariant v0 = anInt;
3029
3030 QVERIFY(v0.canConvert<quint16>());
3031 QCOMPARE(int(qvariant_cast<quint16>(v0)), 32);
3032 QCOMPARE(int(v0.toUInt()), 32);
3033 QCOMPARE(v0.toString(), QString("32"));
3034 }
3035}
3036
3037void tst_QVariant::comparePointers() const
3038{
3039 class MyClass
3040 {
3041 };
3042
3043 MyClass myClass;
3044
3045 QVariant v = QVariant::fromValue<void *>(value: &myClass);
3046 QVariant v2 = QVariant::fromValue<void *>(value: &myClass);
3047
3048 QCOMPARE(v, v2);
3049}
3050
3051struct Data {};
3052Q_DECLARE_METATYPE(Data*)
3053
3054void tst_QVariant::voidStar() const
3055{
3056 char c;
3057 void *p1 = &c;
3058 void *p2 = p1;
3059
3060 QVariant v1, v2;
3061 v1 = QVariant::fromValue(value: p1);
3062 v2 = v1;
3063 QCOMPARE(v1, v2);
3064
3065 v2 = QVariant::fromValue(value: p2);
3066 QCOMPARE(v1, v2);
3067
3068 p2 = 0;
3069 v2 = QVariant::fromValue(value: p2);
3070 QVERIFY(v1 != v2);
3071}
3072
3073void tst_QVariant::dataStar() const
3074{
3075 qRegisterMetaType<Data*>();
3076 Data *p1 = new Data;
3077
3078 QVariant v1 = QVariant::fromValue(value: p1);
3079 QCOMPARE(v1.userType(), qMetaTypeId<Data*>());
3080 QCOMPARE(qvariant_cast<Data*>(v1), p1);
3081
3082 QVariant v2 = v1;
3083 QCOMPARE(v1, v2);
3084
3085 v2 = QVariant::fromValue(value: p1);
3086 QCOMPARE(v1, v2);
3087 delete p1;
3088}
3089
3090void tst_QVariant::canConvertQStringList() const
3091{
3092 QFETCH(bool, canConvert);
3093 QFETCH(QStringList, input);
3094 QFETCH(QString, result);
3095
3096 QVariant v(input);
3097
3098 QCOMPARE(v.canConvert(QVariant::String), canConvert);
3099 QCOMPARE(v.toString(), result);
3100}
3101
3102void tst_QVariant::canConvertQStringList_data() const
3103{
3104 QTest::addColumn<bool>(name: "canConvert");
3105 QTest::addColumn<QStringList>(name: "input");
3106 QTest::addColumn<QString>(name: "result");
3107
3108 QTest::newRow(dataTag: "An empty list") << false << QStringList() << QString();
3109 QTest::newRow(dataTag: "A single item") << true << QStringList(QLatin1String("foo")) << QString::fromLatin1(str: "foo");
3110 QTest::newRow(dataTag: "A single, but empty item") << true << QStringList(QString()) << QString();
3111
3112 QStringList l;
3113 l << "a" << "b";
3114
3115 QTest::newRow(dataTag: "Two items") << false << l << QString();
3116
3117 l << "c";
3118 QTest::newRow(dataTag: "Three items") << false << l << QString();
3119}
3120
3121template<typename T> void convertMetaType()
3122{
3123 QVERIFY(QVariant::fromValue<T>(10).isValid());
3124 QVERIFY(QVariant::fromValue<T>(10).canConvert(QVariant::Int));
3125 QCOMPARE(QVariant::fromValue<T>(10).toInt(), 10);
3126 QCOMPARE(QVariant::fromValue<T>(10), QVariant::fromValue<T>(10));
3127}
3128
3129#define CONVERT_META_TYPE(Type) \
3130 convertMetaType<Type>(); \
3131 if (QTest::currentTestFailed()) \
3132 QFAIL("convertMetaType<" #Type "> failed");
3133
3134void tst_QVariant::canConvertMetaTypeToInt() const
3135{
3136 CONVERT_META_TYPE(long);
3137 CONVERT_META_TYPE(short);
3138 CONVERT_META_TYPE(short);
3139 CONVERT_META_TYPE(unsigned short);
3140 CONVERT_META_TYPE(ushort);
3141 CONVERT_META_TYPE(ulong);
3142 CONVERT_META_TYPE(unsigned long);
3143 CONVERT_META_TYPE(uchar);
3144 CONVERT_META_TYPE(unsigned char);
3145 CONVERT_META_TYPE(char);
3146 CONVERT_META_TYPE(uint);
3147 CONVERT_META_TYPE(unsigned int);
3148}
3149
3150#undef CONVERT_META_TYPE
3151
3152/*!
3153 These calls should not produce any warnings.
3154 */
3155void tst_QVariant::variantToDateTimeWithoutWarnings() const
3156{
3157 {
3158 const QVariant variant(QLatin1String("An invalid QDateTime string"));
3159 const QDateTime dateTime(variant.toDateTime());
3160 QVERIFY(!dateTime.isValid());
3161 }
3162
3163 {
3164 QVariant v1(QLatin1String("xyz"));
3165 v1.convert(targetTypeId: QVariant::DateTime);
3166
3167 QVariant v2(QLatin1String("xyz"));
3168 QDateTime dt1(v2.toDateTime());
3169
3170 const QVariant v3(QLatin1String("xyz"));
3171 const QDateTime dt2(v3.toDateTime());
3172 }
3173}
3174
3175void tst_QVariant::invalidDateTime() const
3176{
3177 QVariant variant(QString::fromLatin1(str: "Invalid date time string"));
3178 QVERIFY(!variant.toDateTime().isValid());
3179 QVERIFY(!variant.convert(QVariant::DateTime));
3180}
3181
3182struct MyClass
3183{
3184 MyClass() : myValue(0) {}
3185 int myValue;
3186};
3187
3188Q_DECLARE_METATYPE( MyClass )
3189
3190void tst_QVariant::loadUnknownUserType()
3191{
3192 qRegisterMetaType<MyClass>(typeName: "MyClass");
3193 QTest::ignoreMessage(type: QtWarningMsg, message: "QVariant::load: unable to load type "
3194 + QByteArray::number(qMetaTypeId<MyClass>()) +".");
3195 char data[] = {0, 0, QMetaType::User >> 8 , char(QMetaType::User), 0, 0, 0, 0, 8, 'M', 'y', 'C', 'l', 'a', 's', 's', 0};
3196
3197 QByteArray ba(data, sizeof(data));
3198 QDataStream ds(&ba, QIODevice::ReadOnly);
3199 QVariant var;
3200 var.load(ds);
3201 QCOMPARE(ds.status(), QDataStream::ReadCorruptData);
3202}
3203
3204void tst_QVariant::loadBrokenUserType()
3205{
3206 QTest::ignoreMessage(type: QtWarningMsg, message: "Trying to construct an instance of an invalid type, type id: 127");
3207 char data[] = {0, 0, 0, 127, 0 };
3208
3209 QByteArray ba(data, sizeof(data));
3210 QDataStream ds(&ba, QIODevice::ReadOnly);
3211 QVariant var;
3212 var.load(ds);
3213 QCOMPARE(ds.status(), QDataStream::Ok);
3214}
3215
3216void tst_QVariant::invalidDate() const
3217{
3218 QString foo("Hello");
3219 QVariant variant(foo);
3220 QVERIFY(!variant.convert(QVariant::Date));
3221
3222 variant = foo;
3223 QVERIFY(!variant.convert(QVariant::DateTime));
3224
3225 variant = foo;
3226 QVERIFY(!variant.convert(QVariant::Time));
3227
3228 variant = foo;
3229 QVERIFY(!variant.convert(QVariant::Int));
3230
3231 variant = foo;
3232 QVERIFY(!variant.convert(QVariant::Double));
3233
3234 variant = foo;
3235 QVERIFY(!variant.convert(QVariant::Type(QMetaType::Float)));
3236}
3237
3238struct WontCompare
3239{
3240 int x,y,z,q,w,e,r,t;
3241};
3242Q_DECLARE_METATYPE(WontCompare);
3243
3244void tst_QVariant::compareCustomTypes() const
3245{
3246 qRegisterMetaType<WontCompare>(typeName: "WontCompare");
3247
3248 WontCompare f1;
3249 f1.x = 0;
3250 const QVariant variant1(QVariant::fromValue(value: f1));
3251
3252 WontCompare f2;
3253 f2.x = 0;
3254 const QVariant variant2(QVariant::fromValue(value: f2));
3255
3256 /* We compare pointers. */
3257 QVERIFY(variant1 != variant2);
3258 QCOMPARE(variant1, variant1);
3259 QCOMPARE(variant2, variant2);
3260}
3261
3262void tst_QVariant::timeToDateTime() const
3263{
3264 const QVariant val(QTime::currentTime());
3265 QVERIFY(!val.canConvert(QVariant::DateTime));
3266 QVERIFY(!val.toDateTime().isValid());
3267}
3268
3269struct CustomComparable
3270{
3271 CustomComparable(int value = 0) : myValue(value) {}
3272 int myValue;
3273
3274 bool operator==(const CustomComparable &other) const
3275 { return other.myValue == myValue; }
3276};
3277
3278Q_DECLARE_METATYPE(CustomComparable)
3279
3280void tst_QVariant::copyingUserTypes() const
3281{
3282 QVariant var;
3283 QVariant varCopy;
3284 const CustomComparable userType = CustomComparable(42);
3285 var.setValue(userType);
3286 varCopy = var;
3287
3288 const CustomComparable copiedType = qvariant_cast<CustomComparable>(v: varCopy);
3289 QCOMPARE(copiedType, userType);
3290 QCOMPARE(copiedType.myValue, 42);
3291}
3292
3293void tst_QVariant::convertBoolToByteArray() const
3294{
3295 QFETCH(QByteArray, input);
3296 QFETCH(bool, canConvert);
3297 QFETCH(bool, value);
3298
3299 const QVariant variant(input);
3300
3301 QCOMPARE(variant.canConvert<bool>(), canConvert);
3302
3303 if(canConvert) {
3304 /* Just call this function so we run the code path. */
3305 QCOMPARE(variant.toBool(), value);
3306 }
3307}
3308
3309void tst_QVariant::convertBoolToByteArray_data() const
3310{
3311 QTest::addColumn<QByteArray>(name: "input");
3312 QTest::addColumn<bool>(name: "canConvert");
3313 QTest::addColumn<bool>(name: "value");
3314
3315 QTest::newRow(dataTag: "false")
3316 << QByteArray("false")
3317 << true
3318 << false;
3319
3320 QTest::newRow(dataTag: "FALSE")
3321 << QByteArray("FALSE")
3322 << true
3323 << false;
3324
3325 QTest::newRow(dataTag: "falSE")
3326 << QByteArray("FALSE")
3327 << true
3328 << false;
3329
3330 QTest::newRow(dataTag: "")
3331 << QByteArray("")
3332 << true
3333 << false;
3334
3335 QTest::newRow(dataTag: "null QByteArray")
3336 << QByteArray()
3337 << true
3338 << false;
3339
3340 QTest::newRow(dataTag: "any-content")
3341 << QByteArray("any-content")
3342 << true
3343 << true;
3344
3345 QTest::newRow(dataTag: "true")
3346 << QByteArray("true")
3347 << true
3348 << true;
3349
3350 QTest::newRow(dataTag: "TRUE")
3351 << QByteArray("TRUE")
3352 << true
3353 << true;
3354
3355 QTest::newRow(dataTag: "trUE")
3356 << QByteArray("trUE")
3357 << true
3358 << true;
3359}
3360
3361void tst_QVariant::convertByteArrayToBool() const
3362{
3363 QFETCH(bool, input);
3364 QFETCH(QByteArray, output);
3365
3366 const QVariant variant(input);
3367 QCOMPARE(variant.type(), QVariant::Bool);
3368 QCOMPARE(variant.toBool(), input);
3369 QVERIFY(variant.canConvert<bool>());
3370
3371 QCOMPARE(variant.toByteArray(), output);
3372}
3373
3374void tst_QVariant::convertByteArrayToBool_data() const
3375{
3376 QTest::addColumn<bool>(name: "input");
3377 QTest::addColumn<QByteArray>(name: "output");
3378
3379 QTest::newRow(dataTag: "false")
3380 << false
3381 << QByteArray("false");
3382
3383 QTest::newRow(dataTag: "true")
3384 << true
3385 << QByteArray("true");
3386}
3387
3388void tst_QVariant::convertIterables() const
3389{
3390 {
3391 QStringList list;
3392 list.append(t: "Hello");
3393 QCOMPARE(QVariant::fromValue(list).value<QVariantList>().count(), list.count());
3394 }
3395 {
3396 QByteArrayList list;
3397 list.append(t: "Hello");
3398 QCOMPARE(QVariant::fromValue(list).value<QVariantList>().count(), list.count());
3399 }
3400 {
3401 QVariantList list;
3402 list.append(t: "World");
3403 QCOMPARE(QVariant::fromValue(list).value<QVariantList>().count(), list.count());
3404 }
3405 {
3406 QMap<QString, int> map;
3407 map.insert(akey: "3", avalue: 4);
3408 QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
3409 QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
3410
3411 map.insertMulti(key: "3", value: 5);
3412 QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
3413 QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
3414 }
3415 {
3416 QVariantMap map;
3417 map.insert(akey: "3", avalue: 4);
3418 QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
3419 QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
3420
3421 map.insertMulti(key: "3", value: 5);
3422 QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
3423 QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
3424 }
3425 {
3426 QHash<QString, int> hash;
3427 hash.insert(akey: "3", avalue: 4);
3428 QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
3429 QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
3430
3431 hash.insertMulti(key: "3", value: 5);
3432 QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
3433 QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
3434 }
3435 {
3436 QVariantHash hash;
3437 hash.insert(akey: "3", avalue: 4);
3438 QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
3439 QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
3440
3441 hash.insertMulti(key: "3", value: 5);
3442 QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
3443 QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
3444 }
3445}
3446
3447/*!
3448 We verify that:
3449 1. Converting the string "9.9" to int fails. This is the behavior of
3450 toLongLong() and hence also QVariant, since it uses it.
3451 2. Converting the QVariant containing the double 9.9 to int works.
3452
3453 Rationale: "9.9" is not a valid int. However, doubles are by definition not
3454 ints and therefore it makes more sense to perform conversion for those.
3455*/
3456void tst_QVariant::toIntFromQString() const
3457{
3458 QVariant first("9.9");
3459 bool ok;
3460 QCOMPARE(first.toInt(&ok), 0);
3461 QVERIFY(!ok);
3462
3463 QCOMPARE(QString("9.9").toLongLong(&ok), qlonglong(0));
3464 QVERIFY(!ok);
3465
3466 QVariant v(9.9);
3467 QCOMPARE(v.toInt(&ok), 10);
3468 QVERIFY(ok);
3469}
3470
3471/*!
3472 We verify that:
3473 1. Conversion from (64 bit) double to int works (no overflow).
3474 2. Same conversion works for QVariant::convert.
3475
3476 Rationale: if 2147483630 is set in float and then converted to int,
3477 there will be overflow and the result will be -2147483648.
3478*/
3479void tst_QVariant::toIntFromDouble() const
3480{
3481 double d = 2147483630; // max int 2147483647
3482 QCOMPARE((int)d, 2147483630);
3483
3484 QVariant var(d);
3485 QVERIFY( var.canConvert( QVariant::Int ) );
3486
3487 bool ok;
3488 int result = var.toInt(ok: &ok);
3489
3490 QVERIFY( ok == true );
3491 QCOMPARE(result, 2147483630);
3492}
3493
3494void tst_QVariant::fpStringRoundtrip_data() const
3495{
3496 QTest::addColumn<QVariant>(name: "number");
3497
3498 QTest::newRow(dataTag: "float") << QVariant(1 + FLT_EPSILON);
3499 QTest::newRow(dataTag: "double") << QVariant(1 + DBL_EPSILON);
3500}
3501
3502void tst_QVariant::fpStringRoundtrip() const
3503{
3504 QFETCH(QVariant, number);
3505
3506 QVariant converted = number;
3507 QVERIFY(converted.convert(QVariant::String));
3508 QVERIFY(converted.convert(number.type()));
3509 QCOMPARE(converted, number);
3510
3511 converted = number;
3512 QVERIFY(converted.convert(QVariant::ByteArray));
3513 QVERIFY(converted.convert(number.type()));
3514 QCOMPARE(converted, number);
3515}
3516
3517void tst_QVariant::numericalConvert_data()
3518{
3519 QTest::addColumn<QVariant>(name: "v");
3520 QTest::addColumn<bool>(name: "isInteger");
3521 QTest::newRow(dataTag: "float") << QVariant(float(5.3)) << false;
3522 QTest::newRow(dataTag: "double") << QVariant(double(5.3)) << false;
3523 QTest::newRow(dataTag: "qreal") << QVariant(qreal(5.3)) << false;
3524 QTest::newRow(dataTag: "int") << QVariant(int(5)) << true;
3525 QTest::newRow(dataTag: "uint") << QVariant(uint(5)) << true;
3526 QTest::newRow(dataTag: "short") << QVariant(short(5)) << true;
3527 QTest::newRow(dataTag: "longlong") << QVariant(quint64(5)) << true;
3528 QTest::newRow(dataTag: "long") << QVariant::fromValue(value: long(5)) << true;
3529 QTest::newRow(dataTag: "stringint") << QVariant(QString::fromLatin1(str: "5")) << true;
3530 QTest::newRow(dataTag: "string") << QVariant(QString::fromLatin1(str: "5.30000019")) << false;
3531}
3532
3533void tst_QVariant::numericalConvert()
3534{
3535 QFETCH(QVariant, v);
3536 QFETCH(bool, isInteger);
3537 double num = isInteger ? 5 : 5.3;
3538
3539 QCOMPARE(v.toFloat() , float(num));
3540 QCOMPARE(float(v.toReal()) , float(num));
3541 QCOMPARE(float(v.toDouble()) , float(num));
3542 if (isInteger) {
3543 QCOMPARE(v.toInt() , int(num));
3544 QCOMPARE(v.toUInt() , uint(num));
3545 QCOMPARE(v.toULongLong() , quint64(num));
3546 QCOMPARE(v.value<ulong>() , ulong(num));
3547 QCOMPARE(v.value<ushort>() , ushort(num));
3548 }
3549 switch (v.userType())
3550 {
3551 case QVariant::Double:
3552 QCOMPARE(v.toString() , QString::number(num, 'g', QLocale::FloatingPointShortest));
3553 break;
3554 case QMetaType::Float:
3555 QCOMPARE(v.toString() ,
3556 QString::number(float(num), 'g', QLocale::FloatingPointShortest));
3557 break;
3558 }
3559}
3560
3561
3562template<class T> void playWithVariant(const T &orig, bool isNull, const QString &toString, double toDouble, bool toBool)
3563{
3564 QVariant v = QVariant::fromValue(orig);
3565 QVERIFY(v.isValid());
3566 QCOMPARE(v.isNull(), isNull);
3567 QCOMPARE(v.toString(), toString);
3568 QCOMPARE(v.toDouble(), toDouble);
3569 QCOMPARE(v.toBool(), toBool);
3570 QCOMPARE(qvariant_cast<T>(v), orig);
3571
3572 {
3573 QVariant v2 = v;
3574 if (!(QTypeInfo<T>::isStatic && QTypeInfo<T>::isComplex)) {
3575 // Type is movable so standard comparison algorithm in QVariant should work
3576 // In a custom type QVariant is not aware of ==operator so it won't be called,
3577 // which may cause problems especially visible when using a not-movable type
3578 QCOMPARE(v2, v);
3579 }
3580 QVERIFY(v2.isValid());
3581 QCOMPARE(v2.isNull(), isNull);
3582 QCOMPARE(v2.toString(), toString);
3583 QCOMPARE(v2.toDouble(), toDouble);
3584 QCOMPARE(v2.toBool(), toBool);
3585 QCOMPARE(qvariant_cast<T>(v2), orig);
3586
3587 QVariant v3;
3588 v = QVariant();
3589 QCOMPARE(v3, v);
3590 v = v2;
3591 if (!(QTypeInfo<T>::isStatic && QTypeInfo<T>::isComplex)) {
3592 // Type is movable so standard comparison algorithm in QVariant should work
3593 // In a custom type QVariant is not aware of ==operator so it won't be called,
3594 // which may cause problems especially visible when using a not-movable type
3595 QCOMPARE(v2, v);
3596 }
3597 QCOMPARE(qvariant_cast<T>(v2), qvariant_cast<T>(v));
3598 QCOMPARE(v2.toString(), toString);
3599 v3 = QVariant::fromValue(orig);
3600
3601 QVERIFY(v3.isValid());
3602 QCOMPARE(v3.isNull(), isNull);
3603 QCOMPARE(v3.toString(), toString);
3604 QCOMPARE(v3.toDouble(), toDouble);
3605 QCOMPARE(v3.toBool(), toBool);
3606 QCOMPARE(qvariant_cast<T>(v3), qvariant_cast<T>(v));
3607 }
3608
3609 QVERIFY(v.isValid());
3610 QCOMPARE(v.isNull(), isNull);
3611 QCOMPARE(v.toString(), toString);
3612 QCOMPARE(v.toDouble(), toDouble);
3613 QCOMPARE(v.toBool(), toBool);
3614 QCOMPARE(qvariant_cast<T>(v), orig);
3615
3616 if (qMetaTypeId<T>() != qMetaTypeId<QVariant>()) {
3617 QCOMPARE(v.userType(), qMetaTypeId<T>());
3618 QCOMPARE(QVariant::typeToName(QVariant::Type(v.userType())), QMetaType::typeName(qMetaTypeId<T>()));
3619 }
3620}
3621
3622#define PLAY_WITH_VARIANT(Orig, IsNull, ToString, ToDouble, ToBool) \
3623 playWithVariant(Orig, IsNull, ToString, ToDouble, ToBool);\
3624 if (QTest::currentTestFailed())\
3625 QFAIL("playWithVariant failed");
3626
3627struct MyPrimitive
3628{
3629 char x, y;
3630 bool operator==(const MyPrimitive &o) const
3631 {
3632 return x == o.x && y == o.y;
3633 }
3634};
3635
3636QT_BEGIN_NAMESPACE
3637Q_DECLARE_TYPEINFO(MyPrimitive, Q_PRIMITIVE_TYPE);
3638QT_END_NAMESPACE
3639
3640struct MyData
3641{
3642 void *ptr;
3643 MyData() : ptr(this) {}
3644 ~MyData()
3645 {
3646 if (ptr != this) qWarning(msg: "%s: object has moved", Q_FUNC_INFO);
3647 }
3648 MyData(const MyData& o) : ptr(this)
3649 {
3650 if (o.ptr != &o) qWarning(msg: "%s: other object has moved", Q_FUNC_INFO);
3651 }
3652 MyData &operator=(const MyData &o)
3653 {
3654 if (ptr != this) qWarning(msg: "%s: object has moved", Q_FUNC_INFO);
3655 if (o.ptr != &o) qWarning(msg: "%s: other object has moved", Q_FUNC_INFO);
3656 return *this;
3657 }
3658 bool operator==(const MyData &o) const
3659 {
3660 if (ptr != this) qWarning(msg: "%s: object has moved", Q_FUNC_INFO);
3661 if (o.ptr != &o) qWarning(msg: "%s: other object has moved", Q_FUNC_INFO);
3662 return true;
3663 }
3664};
3665
3666struct MyMovable
3667{
3668 static int count;
3669 int v;
3670 MyMovable() { v = count++; }
3671 ~MyMovable() { count--; }
3672 MyMovable(const MyMovable &o) : v(o.v) { count++; }
3673
3674 bool operator==(const MyMovable &o) const
3675 {
3676 return v == o.v;
3677 }
3678};
3679
3680int MyMovable::count = 0;
3681
3682struct MyNotMovable
3683{
3684 static int count;
3685 MyNotMovable *that;
3686 MyNotMovable() : that(this) { count++; }
3687 ~MyNotMovable() { QCOMPARE(that, this); count--; }
3688 MyNotMovable(const MyNotMovable &o) : that(this) { QCOMPARE(o.that, &o); count++; }
3689 MyNotMovable &operator=(const MyNotMovable &o) {
3690 bool ok = that == this && o.that == &o;
3691 if (!ok) qFatal(msg: "MyNotMovable has been moved");
3692 return *this;
3693 }
3694
3695 //PLAY_WITH_VARIANT test that they are equal, but never that they are not equal
3696 // so it would be fine just to always return true
3697 bool operator==(const MyNotMovable &o) const
3698 {
3699 bool ok = that == this && o.that == &o;
3700 if (!ok) qFatal(msg: "MyNotMovable has been moved");
3701 return ok;
3702 }
3703};
3704
3705int MyNotMovable::count = 0;
3706
3707struct MyShared : QSharedData {
3708 MyMovable movable;
3709};
3710
3711QT_BEGIN_NAMESPACE
3712Q_DECLARE_TYPEINFO(MyMovable, Q_MOVABLE_TYPE);
3713QT_END_NAMESPACE
3714
3715Q_DECLARE_METATYPE(MyPrimitive)
3716Q_DECLARE_METATYPE(MyData)
3717Q_DECLARE_METATYPE(MyMovable)
3718Q_DECLARE_METATYPE(MyNotMovable)
3719Q_DECLARE_METATYPE(MyPrimitive *)
3720Q_DECLARE_METATYPE(MyData *)
3721Q_DECLARE_METATYPE(MyMovable *)
3722Q_DECLARE_METATYPE(MyNotMovable *)
3723Q_DECLARE_METATYPE(QSharedDataPointer<MyShared>)
3724
3725void tst_QVariant::setValue()
3726{
3727 MyNotMovable t; //we just take a value so that we're sure that it will be shared
3728 QVariant v1 = QVariant::fromValue(value: t);
3729 QVERIFY( v1.isDetached() );
3730 QVariant v2 = v1;
3731 QVERIFY( !v1.isDetached() );
3732 QVERIFY( !v2.isDetached() );
3733
3734 v2.setValue(3); //set an integer value
3735
3736 QVERIFY( v1.isDetached() );
3737 QVERIFY( v2.isDetached() );
3738}
3739
3740void tst_QVariant::moreCustomTypes()
3741{
3742 {
3743 QList<QSize> listSize;
3744 PLAY_WITH_VARIANT(listSize, false, QString(), 0, false);
3745 listSize << QSize(4,5) << QSize(89,23) << QSize(5,6);
3746 PLAY_WITH_VARIANT(listSize, false, QString(), 0, false);
3747 }
3748
3749 {
3750 QString str;
3751 PLAY_WITH_VARIANT(str, true, QString(), 0, false);
3752 str = QString::fromLatin1(str: "123456789.123");
3753 PLAY_WITH_VARIANT(str, false, str, 123456789.123, true);
3754 }
3755
3756 {
3757 QSize size;
3758 PLAY_WITH_VARIANT(size, false, QString(), 0, false);
3759 PLAY_WITH_VARIANT(QSize(45,78), false, QString(), 0, false);
3760 }
3761
3762 {
3763 MyData d;
3764 PLAY_WITH_VARIANT(d, false, QString(), 0, false);
3765 PLAY_WITH_VARIANT(&d, false, QString(), 0, false);
3766 QList<MyData> l;
3767 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3768 l << MyData() << MyData();
3769 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3770 }
3771
3772 {
3773 MyPrimitive d = { .x: 4, .y: 5 };
3774 PLAY_WITH_VARIANT(d, false, QString(), 0, false);
3775 PLAY_WITH_VARIANT(&d, false, QString(), 0, false);
3776 QList<MyPrimitive> l;
3777 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3778 l << d;
3779 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3780 }
3781
3782 {
3783 MyMovable d;
3784 PLAY_WITH_VARIANT(d, false, QString(), 0, false);
3785 PLAY_WITH_VARIANT(&d, false, QString(), 0, false);
3786 QList<MyMovable> l;
3787 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3788 l << MyMovable() << d;
3789 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3790 }
3791 QCOMPARE(MyMovable::count, 0);
3792
3793 QCOMPARE(MyNotMovable::count, 0);
3794 {
3795 MyNotMovable d;
3796 PLAY_WITH_VARIANT(d, false, QString(), 0, false);
3797 PLAY_WITH_VARIANT(&d, false, QString(), 0, false);
3798 QList<MyNotMovable> l;
3799 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3800 l << MyNotMovable() << d;
3801 PLAY_WITH_VARIANT(l, false, QString(), 0, false);
3802 }
3803 QCOMPARE(MyNotMovable::count, 0);
3804
3805 {
3806#ifdef QT_NO_DOUBLECONVERSION
3807 // snprintf cannot do "shortest" conversion and always adds noise.
3808 PLAY_WITH_VARIANT(12.12, false, "12.119999999999999", 12.12, true);
3809#else
3810 // Double can be printed exactly with libdouble-conversion
3811 PLAY_WITH_VARIANT(12.12, false, "12.12", 12.12, true);
3812#endif
3813
3814 // Float is converted to double, adding insignificant bits
3815 PLAY_WITH_VARIANT(12.12f, false, "12.119999885559082", 12.12f, true);
3816
3817 PLAY_WITH_VARIANT('a', false, "a", 'a', true);
3818 PLAY_WITH_VARIANT((unsigned char)('a'), false, "a", 'a', true);
3819 PLAY_WITH_VARIANT( quint8(12), false, "\xc", 12, true);
3820 PLAY_WITH_VARIANT( qint8(13), false, "\xd", 13, true);
3821 PLAY_WITH_VARIANT(quint16(14), false, "14", 14, true);
3822 PLAY_WITH_VARIANT( qint16(15), false, "15", 15, true);
3823 PLAY_WITH_VARIANT(quint32(16), false, "16", 16, true);
3824 PLAY_WITH_VARIANT( qint32(17), false, "17", 17, true);
3825 PLAY_WITH_VARIANT(quint64(18), false, "18", 18, true);
3826 PLAY_WITH_VARIANT( qint64(19), false, "19", 19, true);
3827 PLAY_WITH_VARIANT( qint8(-12), false, QLatin1String("\xf4"), -12, true); // qint8 is char, so it gets converted via QChar
3828 PLAY_WITH_VARIANT( qint16(-13), false, "-13", -13, true);
3829 PLAY_WITH_VARIANT( qint32(-14), false, "-14", -14, true);
3830 PLAY_WITH_VARIANT( qint64(-15), false, "-15", -15, true);
3831 PLAY_WITH_VARIANT(quint64(0), false, "0", 0, false);
3832 PLAY_WITH_VARIANT( true, false, "true", 1, true);
3833 PLAY_WITH_VARIANT( false, false, "false", 0, false);
3834
3835 PLAY_WITH_VARIANT(QString("hello\n"), false, "hello\n", 0, true);
3836 }
3837
3838 {
3839 int i = 5;
3840 PLAY_WITH_VARIANT((void *)(&i), false, QString(), 0, false);
3841 PLAY_WITH_VARIANT((void *)(0), true, QString(), 0, false);
3842 }
3843
3844 {
3845 QVariant v1 = QVariant::fromValue(value: 5);
3846 QVariant v2 = QVariant::fromValue(value: 5.0);
3847 QVariant v3 = QVariant::fromValue(value: quint16(5));
3848 QVariant v4 = 5;
3849 QVariant v5 = QVariant::fromValue(value: MyPrimitive());
3850 QVariant v6 = QVariant::fromValue(value: MyMovable());
3851 QVariant v7 = QVariant::fromValue(value: MyData());
3852 PLAY_WITH_VARIANT(v1, false, "5", 5, true);
3853 PLAY_WITH_VARIANT(v2, false, "5", 5, true);
3854 PLAY_WITH_VARIANT(v3, false, "5", 5, true);
3855 PLAY_WITH_VARIANT(v4, false, "5", 5, true);
3856
3857 PLAY_WITH_VARIANT(v5, false, QString(), 0, false);
3858 }
3859
3860 QCOMPARE(MyMovable::count, 0);
3861 {
3862 QSharedDataPointer<MyShared> d(new MyShared);
3863 PLAY_WITH_VARIANT(d, false, QString(), 0, false);
3864 }
3865 QCOMPARE(MyMovable::count, 0);
3866
3867 {
3868 QList<QList<int> > data;
3869 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3870 data << (QList<int>() << 42);
3871 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3872 }
3873
3874 {
3875 QList<QVector<int> > data;
3876 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3877 data << (QVector<int>() << 42);
3878 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3879 }
3880
3881 {
3882 QList<QSet<int> > data;
3883 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3884 data << (QSet<int>() << 42);
3885 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3886 }
3887
3888#if QT_DEPRECATED_SINCE(5, 15)
3889QT_WARNING_PUSH
3890QT_WARNING_DISABLE_DEPRECATED
3891 {
3892 QList<QLinkedList<int> > data;
3893 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3894 data << (QLinkedList<int>() << 42);
3895 PLAY_WITH_VARIANT(data, false, QString(), 0, false);
3896 }
3897QT_WARNING_POP
3898#endif
3899}
3900
3901void tst_QVariant::movabilityTest()
3902{
3903 // This test checks if QVariant is movable even if an internal data is not movable.
3904 QVERIFY(!MyNotMovable::count);
3905 {
3906 QVariant variant = QVariant::fromValue(value: MyNotMovable());
3907 QVERIFY(MyNotMovable::count);
3908
3909 // prepare destination memory space to which variant will be moved
3910 QVariant buffer[1];
3911 QCOMPARE(buffer[0].type(), QVariant::Invalid);
3912 buffer[0].~QVariant();
3913
3914 memcpy(dest: buffer, src: &variant, n: sizeof(QVariant));
3915 QCOMPARE(buffer[0].type(), QVariant::UserType);
3916 QCOMPARE(buffer[0].userType(), qMetaTypeId<MyNotMovable>());
3917 MyNotMovable tmp(buffer[0].value<MyNotMovable>());
3918
3919 new (&variant) QVariant();
3920 }
3921 QVERIFY(!MyNotMovable::count);
3922}
3923
3924void tst_QVariant::variantInVariant()
3925{
3926 QVariant var1 = 5;
3927 QCOMPARE(var1.type(), QVariant::Int);
3928 QVariant var2 = var1;
3929 QCOMPARE(var2, var1);
3930 QCOMPARE(var2.type(), QVariant::Int);
3931 QVariant var3 = QVariant::fromValue(value: var1);
3932 QCOMPARE(var3, var1);
3933 QCOMPARE(var3.type(), QVariant::Int);
3934 QVariant var4 = qvariant_cast<QVariant>(v: var1);
3935 QCOMPARE(var4, var1);
3936 QCOMPARE(var4.type(), QVariant::Int);
3937 QVariant var5;
3938 var5 = var1;
3939 QCOMPARE(var5, var1);
3940 QCOMPARE(var5.type(), QVariant::Int);
3941 QVariant var6;
3942 var6.setValue(var1);
3943 QCOMPARE(var6, var1);
3944 QCOMPARE(var6.type(), QVariant::Int);
3945
3946 QCOMPARE(QVariant::fromValue(var1), QVariant::fromValue(var2));
3947 QCOMPARE(qvariant_cast<QVariant>(var3), QVariant::fromValue(var4));
3948 QCOMPARE(qvariant_cast<QVariant>(var5), qvariant_cast<QVariant>(var6));
3949
3950 QString str("hello");
3951 QVariant var8 = qvariant_cast<QVariant>(v: QVariant::fromValue(value: QVariant::fromValue(value: str)));
3952 QCOMPARE((int)var8.type(), (int)QVariant::String);
3953 QCOMPARE(qvariant_cast<QString>(QVariant(qvariant_cast<QVariant>(var8))), str);
3954
3955 QVariant var9(qMetaTypeId<QVariant>(), &var1);
3956 QCOMPARE(var9.userType(), qMetaTypeId<QVariant>());
3957 QCOMPARE(qvariant_cast<QVariant>(var9), var1);
3958}
3959
3960struct Convertible {
3961 double d;
3962 operator int() const { return (int)d; }
3963 operator double() const { return d; }
3964 operator QString() const { return QString::number(d); }
3965};
3966
3967Q_DECLARE_METATYPE(Convertible);
3968
3969struct BigConvertible {
3970 double d;
3971 double dummy;
3972 double dummy2;
3973 operator int() const { return (int)d; }
3974 operator double() const { return d; }
3975 operator QString() const { return QString::number(d); }
3976};
3977
3978Q_DECLARE_METATYPE(BigConvertible);
3979Q_STATIC_ASSERT(sizeof(BigConvertible) > sizeof(QVariant));
3980
3981void tst_QVariant::userConversion()
3982{
3983 {
3984 QVERIFY(!(QMetaType::hasRegisteredConverterFunction<int, Convertible>()));
3985 QVERIFY(!(QMetaType::hasRegisteredConverterFunction<double, Convertible>()));
3986 QVERIFY(!(QMetaType::hasRegisteredConverterFunction<QString, Convertible>()));
3987
3988 Convertible c = { .d: 123 };
3989 QVariant v = QVariant::fromValue(value: c);
3990
3991 bool ok;
3992 v.toInt(ok: &ok);
3993 QVERIFY(!ok);
3994
3995 v.toDouble(ok: &ok);
3996 QVERIFY(!ok);
3997
3998 QString s = v.toString();
3999 QVERIFY(s.isEmpty());
4000
4001 QMetaType::registerConverter<Convertible, int>();
4002 QMetaType::registerConverter<Convertible, double>();
4003 QMetaType::registerConverter<Convertible, QString>();
4004
4005 int i = v.toInt(ok: &ok);
4006 QVERIFY(ok);
4007 QCOMPARE(i, 123);
4008
4009 double d = v.toDouble(ok: &ok);
4010 QVERIFY(ok);
4011 QCOMPARE(d, 123.);
4012
4013 s = v.toString();
4014 QCOMPARE(s, QString::fromLatin1("123"));
4015 }
4016
4017 {
4018 QVERIFY(!(QMetaType::hasRegisteredConverterFunction<int, BigConvertible>()));
4019 QVERIFY(!(QMetaType::hasRegisteredConverterFunction<double, BigConvertible>()));
4020 QVERIFY(!(QMetaType::hasRegisteredConverterFunction<QString, BigConvertible>()));
4021
4022 BigConvertible c = { .d: 123, .dummy: 0, .dummy2: 0 };
4023 QVariant v = QVariant::fromValue(value: c);
4024
4025 bool ok;
4026 v.toInt(ok: &ok);
4027 QVERIFY(!ok);
4028
4029 v.toDouble(ok: &ok);
4030 QVERIFY(!ok);
4031
4032 QString s = v.toString();
4033 QVERIFY(s.isEmpty());
4034
4035 QMetaType::registerConverter<BigConvertible, int>();
4036 QMetaType::registerConverter<BigConvertible, double>();
4037 QMetaType::registerConverter<BigConvertible, QString>();
4038
4039 int i = v.toInt(ok: &ok);
4040 QVERIFY(ok);
4041 QCOMPARE(i, 123);
4042
4043 double d = v.toDouble(ok: &ok);
4044 QVERIFY(ok);
4045 QCOMPARE(d, 123.);
4046
4047 s = v.toString();
4048 QCOMPARE(s, QString::fromLatin1("123"));
4049 }
4050}
4051
4052void tst_QVariant::modelIndexConversion()
4053{
4054 QVariant modelIndexVariant = QModelIndex();
4055 QVERIFY(modelIndexVariant.canConvert(QMetaType::QPersistentModelIndex));
4056 QVERIFY(modelIndexVariant.convert(QMetaType::QPersistentModelIndex));
4057 QCOMPARE(modelIndexVariant.type(), QVariant::PersistentModelIndex);
4058 QVERIFY(modelIndexVariant.canConvert(QMetaType::QModelIndex));
4059 QVERIFY(modelIndexVariant.convert(QMetaType::QModelIndex));
4060 QCOMPARE(modelIndexVariant.type(), QVariant::ModelIndex);
4061}
4062
4063class Forward;
4064Q_DECLARE_OPAQUE_POINTER(Forward*)
4065Q_DECLARE_METATYPE(Forward*)
4066
4067void tst_QVariant::forwardDeclare()
4068{
4069 Forward *f = 0;
4070 QVariant v = QVariant::fromValue(value: f);
4071 QCOMPARE(qvariant_cast<Forward*>(v), f);
4072}
4073
4074void tst_QVariant::loadQt5Stream_data()
4075{
4076 dataStream_data(version: QDataStream::Qt_5_0);
4077}
4078
4079void tst_QVariant::loadQt5Stream()
4080{
4081 loadQVariantFromDataStream(version: QDataStream::Qt_5_0);
4082}
4083
4084void tst_QVariant::saveQt5Stream_data()
4085{
4086 dataStream_data(version: QDataStream::Qt_5_0);
4087}
4088
4089void tst_QVariant::saveQt5Stream()
4090{
4091 saveQVariantFromDataStream(version: QDataStream::Qt_5_0);
4092}
4093
4094void tst_QVariant::loadQt4Stream_data()
4095{
4096 dataStream_data(version: QDataStream::Qt_4_9);
4097}
4098
4099void tst_QVariant::loadQt4Stream()
4100{
4101 loadQVariantFromDataStream(version: QDataStream::Qt_4_9);
4102}
4103
4104void tst_QVariant::saveQt4Stream_data()
4105{
4106 dataStream_data(version: QDataStream::Qt_4_9);
4107}
4108
4109void tst_QVariant::saveQt4Stream()
4110{
4111 saveQVariantFromDataStream(version: QDataStream::Qt_4_9);
4112}
4113
4114void tst_QVariant::dataStream_data(QDataStream::Version version)
4115{
4116 QTest::addColumn<QString>(name: "fileName");
4117
4118 QString path;
4119 switch (version) {
4120 case QDataStream::Qt_4_9:
4121 path = QString::fromLatin1(str: "qt4.9");
4122 break;
4123 case QDataStream::Qt_5_0:
4124 path = QString::fromLatin1(str: "qt5.0");
4125 break;
4126 default:
4127 Q_UNIMPLEMENTED();
4128 }
4129
4130 path = path.prepend(s: ":/stream/").append(s: "/");
4131 QDir dir(path);
4132 uint i = 0;
4133 foreach (const QFileInfo &fileInfo, dir.entryInfoList(QStringList() << "*.bin")) {
4134 QTest::newRow(dataTag: (path + fileInfo.fileName()).toLatin1()) << fileInfo.filePath();
4135 i += 1;
4136 }
4137 QVERIFY(i > 10);
4138}
4139
4140void tst_QVariant::loadQVariantFromDataStream(QDataStream::Version version)
4141{
4142 QFETCH(QString, fileName);
4143
4144 QFile file(fileName);
4145 QVERIFY(file.open(QIODevice::ReadOnly));
4146
4147 QDataStream stream(&file);
4148 stream.setVersion(version);
4149
4150 QString typeName;
4151 QVariant loadedVariant;
4152 stream >> typeName >> loadedVariant;
4153
4154 const int id = QMetaType::type(typeName: typeName.toLatin1());
4155 if (id == QMetaType::Void) {
4156 // Void type is not supported by QVariant
4157 return;
4158 }
4159
4160 QVariant constructedVariant(static_cast<QVariant::Type>(id));
4161 QCOMPARE(constructedVariant.userType(), id);
4162 QCOMPARE(QMetaType::typeName(loadedVariant.userType()), typeName.toLatin1().constData());
4163 QCOMPARE(loadedVariant.userType(), constructedVariant.userType());
4164}
4165
4166void tst_QVariant::saveQVariantFromDataStream(QDataStream::Version version)
4167{
4168 QFETCH(QString, fileName);
4169
4170 QFile file(fileName);
4171 QVERIFY(file.open(QIODevice::ReadOnly));
4172 QDataStream dataFileStream(&file);
4173
4174 QString typeName;
4175 dataFileStream >> typeName;
4176 QByteArray data = file.readAll();
4177 const int id = QMetaType::type(typeName: typeName.toLatin1());
4178 if (id == QMetaType::Void) {
4179 // Void type is not supported by QVariant
4180 return;
4181 }
4182
4183 QBuffer buffer;
4184 buffer.open(openMode: QIODevice::ReadWrite);
4185 QDataStream stream(&buffer);
4186 stream.setVersion(version);
4187
4188 QVariant constructedVariant(static_cast<QVariant::Type>(id));
4189 QCOMPARE(constructedVariant.userType(), id);
4190 stream << constructedVariant;
4191
4192 // We are testing QVariant there is no point in testing full array.
4193 QCOMPARE(buffer.data().left(5), data.left(5));
4194
4195 buffer.seek(off: 0);
4196 QVariant recunstructedVariant;
4197 stream >> recunstructedVariant;
4198 QCOMPARE(recunstructedVariant.userType(), constructedVariant.userType());
4199}
4200
4201void tst_QVariant::debugStream_data()
4202{
4203 QTest::addColumn<QVariant>(name: "variant");
4204 QTest::addColumn<int>(name: "typeId");
4205 for (int id = 0; id < QMetaType::LastCoreType + 1; ++id) {
4206 const char *tagName = QMetaType::typeName(type: id);
4207 if (!tagName)
4208 continue;
4209 if (id != QMetaType::Void) {
4210 QTest::newRow(dataTag: tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
4211 }
4212 }
4213 QTest::newRow(dataTag: "QBitArray(111)") << QVariant(QBitArray(3, true)) << qMetaTypeId<QBitArray>();
4214 QTest::newRow(dataTag: "CustomStreamableClass") << QVariant(qMetaTypeId<CustomStreamableClass>(), 0) << qMetaTypeId<CustomStreamableClass>();
4215 QTest::newRow(dataTag: "MyClass") << QVariant(qMetaTypeId<MyClass>(), 0) << qMetaTypeId<MyClass>();
4216 QTest::newRow(dataTag: "InvalidVariant") << QVariant() << int(QMetaType::UnknownType);
4217 QTest::newRow(dataTag: "CustomQObject") << QVariant::fromValue(value: this) << qMetaTypeId<tst_QVariant*>();
4218}
4219
4220void tst_QVariant::debugStream()
4221{
4222 QFETCH(QVariant, variant);
4223 QFETCH(int, typeId);
4224
4225 MessageHandler msgHandler(typeId);
4226 qDebug() << variant;
4227 QVERIFY(msgHandler.testPassed());
4228}
4229
4230struct MessageHandlerType : public MessageHandler
4231{
4232 MessageHandlerType(const int typeId)
4233 : MessageHandler(typeId, handler)
4234 {}
4235 static void handler(QtMsgType, const QMessageLogContext &, const QString &msg)
4236 {
4237 // Format itself is not important, but basic data as a type name should be included in the output
4238 ok = msg.startsWith(s: "QVariant::");
4239 QVERIFY2(ok, (QString::fromLatin1("Message is not started correctly: '") + msg + '\'').toLatin1().constData());
4240 ok &= (currentId == QMetaType::UnknownType
4241 ? msg.contains(s: "Invalid")
4242 : msg.contains(s: QMetaType::typeName(type: currentId)));
4243 QVERIFY2(ok, (QString::fromLatin1("Message doesn't contain type name: '") + msg + '\'').toLatin1().constData());
4244 }
4245};
4246
4247void tst_QVariant::debugStreamType_data()
4248{
4249 debugStream_data();
4250}
4251
4252void tst_QVariant::debugStreamType()
4253{
4254 QFETCH(QVariant, variant);
4255 QFETCH(int, typeId);
4256
4257 MessageHandlerType msgHandler(typeId);
4258 qDebug() << QVariant::Type(typeId);
4259 QVERIFY(msgHandler.testPassed());
4260}
4261
4262void tst_QVariant::implicitConstruction()
4263{
4264 // This is a compile-time test
4265 QVariant v;
4266
4267#define FOR_EACH_CORE_CLASS(F) \
4268 F(Char) \
4269 F(String) \
4270 F(StringList) \
4271 F(ByteArray) \
4272 F(BitArray) \
4273 F(Date) \
4274 F(Time) \
4275 F(DateTime) \
4276 F(Url) \
4277 F(Locale) \
4278 F(Rect) \
4279 F(RectF) \
4280 F(Size) \
4281 F(SizeF) \
4282 F(Line) \
4283 F(LineF) \
4284 F(Point) \
4285 F(PointF) \
4286 F(RegExp) \
4287 F(EasingCurve) \
4288 F(Uuid) \
4289 F(ModelIndex) \
4290 F(PersistentModelIndex) \
4291 F(RegularExpression) \
4292 F(JsonValue) \
4293 F(JsonObject) \
4294 F(JsonArray) \
4295 F(JsonDocument) \
4296
4297#define CONSTRUCT(TYPE) \
4298 { \
4299 Q##TYPE t; \
4300 v = t; \
4301 t = v.to##TYPE(); \
4302 QVERIFY(true); \
4303 }
4304
4305 FOR_EACH_CORE_CLASS(CONSTRUCT)
4306
4307#undef CONSTRUCT
4308#undef FOR_EACH_CORE_CLASS
4309}
4310
4311void tst_QVariant::saveInvalid_data()
4312{
4313 QTest::addColumn<unsigned>(name: "version");
4314 for (unsigned version = QDataStream::Qt_5_0; version > QDataStream::Qt_1_0; --version)
4315 QTest::newRow(dataTag: QString::number(version).toUtf8()) << version;
4316}
4317
4318void tst_QVariant::saveInvalid()
4319{
4320 QFETCH(unsigned, version);
4321
4322 QByteArray data;
4323 QDataStream stream(&data, QIODevice::WriteOnly);
4324 stream.setVersion(version);
4325 stream << QVariant();
4326 QCOMPARE(stream.status(), QDataStream::Ok);
4327 QVERIFY(data.size() >= 4);
4328 QCOMPARE(int(data.constData()[0]), 0);
4329 QCOMPARE(int(data.constData()[1]), 0);
4330 QCOMPARE(int(data.constData()[2]), 0);
4331 QCOMPARE(int(data.constData()[3]), 0);
4332}
4333
4334void tst_QVariant::saveNewBuiltinWithOldStream()
4335{
4336 QByteArray data;
4337 QDataStream stream(&data, QIODevice::WriteOnly);
4338 stream.setVersion(QDataStream::Qt_3_1);
4339 stream << QVariant::fromValue<QJsonValue>(value: 123); // QJsonValue class was introduced in Qt5
4340 QCOMPARE(stream.status(), QDataStream::Ok);
4341 QVERIFY(data.size() >= 4);
4342 QCOMPARE(int(data.constData()[0]), 0);
4343 QCOMPARE(int(data.constData()[1]), 0);
4344 QCOMPARE(int(data.constData()[2]), 0);
4345 QCOMPARE(int(data.constData()[3]), 0);
4346}
4347
4348template<typename Container, typename Value_Type = typename Container::value_type>
4349struct ContainerAPI
4350{
4351 static void insert(Container &container, typename Container::value_type value)
4352 {
4353 container.push_back(value);
4354 }
4355
4356 static bool compare(const QVariant &variant, typename Container::value_type value)
4357 {
4358 return variant.value<typename Container::value_type>() == value;
4359 }
4360 static bool compare(QVariant variant, const QVariant &value)
4361 {
4362 return variant == value;
4363 }
4364};
4365
4366template<typename Container>
4367struct ContainerAPI<Container, QVariant>
4368{
4369 static void insert(Container &container, int value)
4370 {
4371 container.push_back(QVariant::fromValue(value));
4372 }
4373
4374 static bool compare(QVariant variant, const QVariant &value)
4375 {
4376 return variant == value;
4377 }
4378};
4379
4380template<typename Container>
4381struct ContainerAPI<Container, QString>
4382{
4383 static void insert(Container &container, int value)
4384 {
4385 container.push_back(QString::number(value));
4386 }
4387
4388 static bool compare(const QVariant &variant, QString value)
4389 {
4390 return variant.value<QString>() == value;
4391 }
4392 static bool compare(QVariant variant, const QVariant &value)
4393 {
4394 return variant == value;
4395 }
4396};
4397
4398template<typename Container>
4399struct ContainerAPI<Container, QByteArray>
4400{
4401 static void insert(Container &container, int value)
4402 {
4403 container.push_back(QByteArray::number(value));
4404 }
4405
4406 static bool compare(const QVariant &variant, QByteArray value)
4407 {
4408 return variant.value<QByteArray>() == value;
4409 }
4410 static bool compare(QVariant variant, const QVariant &value)
4411 {
4412 return variant == value;
4413 }
4414};
4415
4416#ifdef __has_include
4417# if __has_include(<forward_list>)
4418# define TEST_FORWARD_LIST
4419# include <forward_list>
4420
4421Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::forward_list)
4422
4423// Test that explicit declaration does not degrade features.
4424Q_DECLARE_METATYPE(std::forward_list<int>)
4425
4426template<typename Value_Type>
4427struct ContainerAPI<std::forward_list<Value_Type> >
4428{
4429 static void insert(std::forward_list<Value_Type> &container, Value_Type value)
4430 {
4431 container.push_front(value);
4432 }
4433 static bool compare(const QVariant &variant, Value_Type value)
4434 {
4435 return variant.value<Value_Type>() == value;
4436 }
4437 static bool compare(QVariant variant, const QVariant &value)
4438 {
4439 return variant == value;
4440 }
4441};
4442
4443template<>
4444struct ContainerAPI<std::forward_list<QVariant> >
4445{
4446 static void insert(std::forward_list<QVariant> &container, int value)
4447 {
4448 container.push_front(val: QVariant::fromValue(value));
4449 }
4450
4451 static bool compare(QVariant variant, const QVariant &value)
4452 {
4453 return variant == value;
4454 }
4455};
4456
4457template<>
4458struct ContainerAPI<std::forward_list<QString> >
4459{
4460 static void insert(std::forward_list<QString> &container, int value)
4461 {
4462 container.push_front(val: QString::number(value));
4463 }
4464 static bool compare(const QVariant &variant, QString value)
4465 {
4466 return variant.value<QString>() == value;
4467 }
4468 static bool compare(QVariant variant, const QVariant &value)
4469 {
4470 return variant == value;
4471 }
4472};
4473# endif // __has_include(<forward_list>)
4474#endif // __has_include
4475
4476template<typename Container>
4477struct KeyGetter
4478{
4479 static const typename Container::key_type & get(const typename Container::const_iterator &it)
4480 {
4481 return it.key();
4482 }
4483 static const typename Container::mapped_type & value(const typename Container::const_iterator &it)
4484 {
4485 return it.value();
4486 }
4487};
4488
4489template<typename T, typename U>
4490struct KeyGetter<std::map<T, U> >
4491{
4492 static const T & get(const typename std::map<T, U>::const_iterator &it)
4493 {
4494 return it->first;
4495 }
4496 static const U & value(const typename std::map<T, U>::const_iterator &it)
4497 {
4498 return it->second;
4499 }
4500};
4501
4502
4503// We have no built-in defines to check the stdlib features.
4504// #define TEST_UNORDERED_MAP
4505
4506#ifdef TEST_UNORDERED_MAP
4507#include <unordered_map>
4508typedef std::unordered_map<int, bool> StdUnorderedMap_int_bool;
4509
4510Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::unordered_map)
4511
4512Q_DECLARE_METATYPE(StdUnorderedMap_int_bool)
4513
4514template<typename T, typename U>
4515struct KeyGetter<std::unordered_map<T, U> >
4516{
4517 static const T & get(const typename std::unordered_map<T, U>::const_iterator &it)
4518 {
4519 return it->first;
4520 }
4521 static const U & value(const typename std::unordered_map<T, U>::const_iterator &it)
4522 {
4523 return it->second;
4524 }
4525};
4526#endif
4527
4528void tst_QVariant::iterateContainerElements()
4529{
4530#ifdef Q_COMPILER_RANGE_FOR
4531
4532#define TEST_RANGE_FOR(CONTAINER) \
4533 numSeen = 0; \
4534 containerIter = intList.begin(); \
4535 for (QVariant v : listIter) { \
4536 QVERIFY(ContainerAPI<CONTAINER >::compare(v, *containerIter)); \
4537 QVERIFY(ContainerAPI<CONTAINER >::compare(v, varList.at(numSeen))); \
4538 ++containerIter; \
4539 ++numSeen; \
4540 } \
4541 QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end()));
4542
4543#else
4544
4545#define TEST_RANGE_FOR(CONTAINER)
4546
4547#endif
4548
4549#define TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(CONTAINER) \
4550 { \
4551 int numSeen = 0; \
4552 CONTAINER intList; \
4553 ContainerAPI<CONTAINER >::insert(intList, 1); \
4554 ContainerAPI<CONTAINER >::insert(intList, 2); \
4555 ContainerAPI<CONTAINER >::insert(intList, 3); \
4556 \
4557 QVariant listVariant = QVariant::fromValue(intList); \
4558 QVERIFY(listVariant.canConvert<QVariantList>()); \
4559 QVariantList varList = listVariant.value<QVariantList>(); \
4560 QCOMPARE(varList.size(), (int)std::distance(intList.begin(), intList.end())); \
4561 QSequentialIterable listIter = listVariant.value<QSequentialIterable>(); \
4562 QCOMPARE(varList.size(), listIter.size()); \
4563 \
4564 CONTAINER::iterator containerIter = intList.begin(); \
4565 const CONTAINER::iterator containerEnd = intList.end(); \
4566 for (int i = 0; i < listIter.size(); ++i, ++containerIter, ++numSeen) \
4567 { \
4568 QVERIFY(ContainerAPI<CONTAINER >::compare(listIter.at(i), *containerIter)); \
4569 QVERIFY(ContainerAPI<CONTAINER >::compare(listIter.at(i), varList.at(i))); \
4570 } \
4571 QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end())); \
4572 QCOMPARE(containerIter, containerEnd); \
4573 \
4574 containerIter = intList.begin(); \
4575 numSeen = 0; \
4576 Q_FOREACH (const QVariant &v, listIter) { \
4577 QVERIFY(ContainerAPI<CONTAINER >::compare(v, *containerIter)); \
4578 QVERIFY(ContainerAPI<CONTAINER >::compare(v, varList.at(numSeen))); \
4579 ++containerIter; \
4580 ++numSeen; \
4581 } \
4582 QCOMPARE(numSeen, (int)std::distance(intList.begin(), intList.end())); \
4583 TEST_RANGE_FOR(CONTAINER) \
4584 }
4585
4586#define TEST_SEQUENTIAL_ITERATION(CONTAINER, VALUE_TYPE) \
4587 TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(CONTAINER<VALUE_TYPE > )
4588
4589
4590 TEST_SEQUENTIAL_ITERATION(QVector, int)
4591 TEST_SEQUENTIAL_ITERATION(QVector, QVariant)
4592 TEST_SEQUENTIAL_ITERATION(QVector, QString)
4593 TEST_SEQUENTIAL_ITERATION(QQueue, int)
4594 TEST_SEQUENTIAL_ITERATION(QQueue, QVariant)
4595 TEST_SEQUENTIAL_ITERATION(QQueue, QString)
4596 TEST_SEQUENTIAL_ITERATION(QList, int)
4597 TEST_SEQUENTIAL_ITERATION(QList, QVariant)
4598 TEST_SEQUENTIAL_ITERATION(QList, QString)
4599 TEST_SEQUENTIAL_ITERATION(QList, QByteArray)
4600 TEST_SEQUENTIAL_ITERATION(QStack, int)
4601 TEST_SEQUENTIAL_ITERATION(QStack, QVariant)
4602 TEST_SEQUENTIAL_ITERATION(QStack, QString)
4603 TEST_SEQUENTIAL_ITERATION(std::vector, int)
4604 TEST_SEQUENTIAL_ITERATION(std::vector, QVariant)
4605 TEST_SEQUENTIAL_ITERATION(std::vector, QString)
4606 TEST_SEQUENTIAL_ITERATION(std::list, int)
4607 TEST_SEQUENTIAL_ITERATION(std::list, QVariant)
4608 TEST_SEQUENTIAL_ITERATION(std::list, QString)
4609 TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(QStringList)
4610 TEST_SEQUENTIAL_ITERATION_ON_FULL_NAME(QByteArrayList)
4611
4612#ifdef TEST_FORWARD_LIST
4613 TEST_SEQUENTIAL_ITERATION(std::forward_list, int)
4614 TEST_SEQUENTIAL_ITERATION(std::forward_list, QVariant)
4615 TEST_SEQUENTIAL_ITERATION(std::forward_list, QString)
4616#endif
4617
4618 {
4619 QVariantList ints;
4620 ints << 1 << 2 << 3;
4621 QVariant var = QVariant::fromValue(value: ints);
4622 QSequentialIterable iter = var.value<QSequentialIterable>();
4623 QSequentialIterable::const_iterator it = iter.begin();
4624 QSequentialIterable::const_iterator end = iter.end();
4625 QCOMPARE(ints.at(1), *(it + 1));
4626 int i = 0;
4627 for ( ; it != end; ++it, ++i) {
4628 QCOMPARE(ints.at(i), *it);
4629 }
4630
4631 it = iter.begin();
4632
4633 QVariantList intsCopy;
4634 intsCopy << *(it++);
4635 intsCopy << *(it++);
4636 intsCopy << *(it++);
4637 QCOMPARE(ints, intsCopy);
4638 }
4639
4640#define TEST_ASSOCIATIVE_ITERATION(CONTAINER, KEY_TYPE, MAPPED_TYPE) \
4641 { \
4642 int numSeen = 0; \
4643 CONTAINER<KEY_TYPE, MAPPED_TYPE> mapping; \
4644 mapping[5] = true; \
4645 mapping[15] = false; \
4646 \
4647 QVariant mappingVariant = QVariant::fromValue(mapping); \
4648 QVariantMap varMap = mappingVariant.value<QVariantMap>(); \
4649 QVariantMap varHash = mappingVariant.value<QVariantMap>(); \
4650 QAssociativeIterable mappingIter = mappingVariant.value<QAssociativeIterable>(); \
4651 \
4652 CONTAINER<KEY_TYPE, MAPPED_TYPE>::const_iterator containerIter = mapping.begin(); \
4653 const CONTAINER<KEY_TYPE, MAPPED_TYPE>::const_iterator containerEnd = mapping.end(); \
4654 for ( ; containerIter != containerEnd; ++containerIter, ++numSeen) \
4655 { \
4656 MAPPED_TYPE expected = KeyGetter<CONTAINER<KEY_TYPE, MAPPED_TYPE> >::value(containerIter); \
4657 KEY_TYPE key = KeyGetter<CONTAINER<KEY_TYPE, MAPPED_TYPE> >::get(containerIter); \
4658 MAPPED_TYPE actual = mappingIter.value(key).value<MAPPED_TYPE >(); \
4659 QCOMPARE(varMap.value(QString::number(key)).value<MAPPED_TYPE>(), expected); \
4660 QCOMPARE(varHash.value(QString::number(key)).value<MAPPED_TYPE>(), expected); \
4661 QCOMPARE(actual, expected); \
4662 const QAssociativeIterable::const_iterator it = mappingIter.find(key); \
4663 QVERIFY(it != mappingIter.end()); \
4664 QCOMPARE(it.value().value<MAPPED_TYPE>(), expected); \
4665 } \
4666 QCOMPARE(numSeen, (int)std::distance(mapping.begin(), mapping.end())); \
4667 QCOMPARE(containerIter, containerEnd); \
4668 QVERIFY(mappingIter.find(10) == mappingIter.end()); \
4669 }
4670
4671 TEST_ASSOCIATIVE_ITERATION(QHash, int, bool)
4672 TEST_ASSOCIATIVE_ITERATION(QMap, int, bool)
4673 TEST_ASSOCIATIVE_ITERATION(std::map, int, bool)
4674#ifdef TEST_UNORDERED_MAP
4675 TEST_ASSOCIATIVE_ITERATION(std::unordered_map, int, bool)
4676#endif
4677
4678 {
4679 QMap<int, QString> mapping;
4680 mapping.insert(akey: 1, avalue: "one");
4681 mapping.insert(akey: 2, avalue: "two");
4682 mapping.insert(akey: 3, avalue: "three");
4683 QVariant var = QVariant::fromValue(value: mapping);
4684 QAssociativeIterable iter = var.value<QAssociativeIterable>();
4685 QAssociativeIterable::const_iterator it = iter.begin();
4686 QAssociativeIterable::const_iterator end = iter.end();
4687 QCOMPARE(*(mapping.begin() + 1), (*(it + 1)).toString());
4688 int i = 0;
4689 for ( ; it != end; ++it, ++i) {
4690 QCOMPARE(*(mapping.begin() + i), (*it).toString());
4691 }
4692
4693 QVariantList nums;
4694 nums << "one" << "two" << "three";
4695
4696 it = iter.begin();
4697
4698 QVariantList numsCopy;
4699 numsCopy << *(it++);
4700 numsCopy << *(it++);
4701 numsCopy << *(it++);
4702 QCOMPARE(nums, numsCopy);
4703 }
4704}
4705
4706void tst_QVariant::pairElements()
4707{
4708 typedef QPair<QVariant, QVariant> QVariantPair;
4709
4710#define TEST_PAIR_ELEMENT_ACCESS(PAIR, T1, T2, VALUE1, VALUE2) \
4711 { \
4712 PAIR<T1, T2> p(VALUE1, VALUE2); \
4713 QVariant v = QVariant::fromValue(p); \
4714 \
4715 QVERIFY(v.canConvert<QVariantPair>()); \
4716 QVariantPair pi = v.value<QVariantPair>(); \
4717 QCOMPARE(pi.first, QVariant::fromValue(VALUE1)); \
4718 QCOMPARE(pi.second, QVariant::fromValue(VALUE2)); \
4719 }
4720
4721 TEST_PAIR_ELEMENT_ACCESS(QPair, int, int, 4, 5)
4722 TEST_PAIR_ELEMENT_ACCESS(std::pair, int, int, 4, 5)
4723 TEST_PAIR_ELEMENT_ACCESS(QPair, QString, QString, QStringLiteral("one"), QStringLiteral("two"))
4724 TEST_PAIR_ELEMENT_ACCESS(std::pair, QString, QString, QStringLiteral("one"), QStringLiteral("two"))
4725 TEST_PAIR_ELEMENT_ACCESS(QPair, QVariant, QVariant, 4, 5)
4726 TEST_PAIR_ELEMENT_ACCESS(std::pair, QVariant, QVariant, 4, 5)
4727 TEST_PAIR_ELEMENT_ACCESS(QPair, QVariant, int, 41, 15)
4728 TEST_PAIR_ELEMENT_ACCESS(std::pair, QVariant, int, 34, 65)
4729 TEST_PAIR_ELEMENT_ACCESS(QPair, int, QVariant, 24, 25)
4730 TEST_PAIR_ELEMENT_ACCESS(std::pair, int, QVariant, 44, 15)
4731}
4732
4733enum EnumTest_Enum0 { EnumTest_Enum0_value = 42, EnumTest_Enum0_negValue = -8 };
4734Q_DECLARE_METATYPE(EnumTest_Enum0)
4735enum EnumTest_Enum1 : qint64 { EnumTest_Enum1_value = 42, EnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
4736Q_DECLARE_METATYPE(EnumTest_Enum1)
4737
4738enum EnumTest_Enum3 : qint64 { EnumTest_Enum3_value = -47, EnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5 };
4739Q_DECLARE_METATYPE(EnumTest_Enum3)
4740enum EnumTest_Enum4 : quint64 { EnumTest_Enum4_value = 47, EnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
4741Q_DECLARE_METATYPE(EnumTest_Enum4)
4742enum EnumTest_Enum5 : uint { EnumTest_Enum5_value = 47 };
4743Q_DECLARE_METATYPE(EnumTest_Enum5)
4744enum EnumTest_Enum6 : uchar { EnumTest_Enum6_value = 47 };
4745Q_DECLARE_METATYPE(EnumTest_Enum6)
4746enum class EnumTest_Enum7 { EnumTest_Enum7_value = 47, ensureSignedEnum7 = -1 };
4747Q_DECLARE_METATYPE(EnumTest_Enum7)
4748enum EnumTest_Enum8 : short { EnumTest_Enum8_value = 47 };
4749Q_DECLARE_METATYPE(EnumTest_Enum8)
4750
4751template<typename Enum> void testVariant(Enum value, bool *ok)
4752{
4753 *ok = false;
4754 QVariant var = QVariant::fromValue(value);
4755
4756 QCOMPARE(var.userType(), qMetaTypeId<Enum>());
4757
4758 QVERIFY(var.canConvert<Enum>());
4759 QVERIFY(var.canConvert<int>());
4760 QVERIFY(var.canConvert<unsigned int>());
4761 QVERIFY(var.canConvert<short>());
4762 QVERIFY(var.canConvert<unsigned short>());
4763 QVERIFY(var.canConvert<qint64>());
4764 QVERIFY(var.canConvert<quint64>());
4765
4766
4767 QCOMPARE(var.value<Enum>(), value);
4768 QCOMPARE(var.value<int>(), static_cast<int>(value));
4769 QCOMPARE(var.value<uint>(), static_cast<uint>(value));
4770 QCOMPARE(var.value<short>(), static_cast<short>(value));
4771 QCOMPARE(var.value<unsigned short>(), static_cast<unsigned short>(value));
4772 QCOMPARE(var.value<qint64>(), static_cast<qint64>(value));
4773 if (sizeof(value) < 8 && static_cast<qint64>(value) < 0) {
4774 QEXPECT_FAIL("", "The metatype system don't store the sign of enums", Continue);
4775 // The value is stored internaly with 32 bit. When asked to convert it to 64 bit unsigned,
4776 // we consider that the value was unsigned, so we don't extent the bit signs
4777 }
4778 QCOMPARE(var.value<quint64>(), static_cast<quint64>(value));
4779
4780 QVariant var2 = var;
4781 QVERIFY(var2.convert(QMetaType::Int));
4782 QCOMPARE(var2.value<int>(), static_cast<int>(value));
4783
4784 if ((static_cast<qint64>(value) <= INT_MAX) && (static_cast<qint64>(value) >= INT_MIN)) {
4785 int intValue = static_cast<int>(value);
4786 QVariant intVar = intValue;
4787 QVERIFY(intVar.canConvert<Enum>());
4788 QCOMPARE(intVar.value<Enum>(), value);
4789 }
4790 qint64 longValue = static_cast<qint64>(value);
4791 QVERIFY(QVariant(longValue).canConvert<Enum>());
4792 QCOMPARE(QVariant(longValue).value<Enum>(), value);
4793
4794 *ok = true;
4795}
4796
4797void tst_QVariant::enums()
4798{
4799 bool ok = false;
4800 testVariant(value: EnumTest_Enum0_value, ok: &ok);
4801 QVERIFY(ok);
4802 testVariant(value: EnumTest_Enum0_negValue, ok: &ok);
4803 QVERIFY(ok);
4804 testVariant(value: EnumTest_Enum1_value, ok: &ok);
4805 QVERIFY(ok);
4806 testVariant(value: EnumTest_Enum1_bigValue, ok: &ok);
4807 QVERIFY(ok);
4808 testVariant(value: EnumTest_Enum3::EnumTest_Enum3_value, ok: &ok);
4809 QVERIFY(ok);
4810 testVariant(value: EnumTest_Enum3::EnumTest_Enum3_bigValue, ok: &ok);
4811 QVERIFY(ok);
4812 testVariant(value: EnumTest_Enum4::EnumTest_Enum4_value, ok: &ok);
4813 QVERIFY(ok);
4814 testVariant(value: EnumTest_Enum4::EnumTest_Enum4_bigValue, ok: &ok);
4815 QVERIFY(ok);
4816 testVariant(value: EnumTest_Enum5::EnumTest_Enum5_value, ok: &ok);
4817 QVERIFY(ok);
4818 testVariant(value: EnumTest_Enum6::EnumTest_Enum6_value, ok: &ok);
4819 QVERIFY(ok);
4820 testVariant(value: EnumTest_Enum7::EnumTest_Enum7_value, ok: &ok);
4821 QVERIFY(ok);
4822 testVariant(value: EnumTest_Enum8::EnumTest_Enum8_value, ok: &ok);
4823 QVERIFY(ok);
4824 testVariant(value: EnumTest_Enum3::EnumTest_Enum3_value, ok: &ok);
4825 QVERIFY(ok);
4826}
4827
4828template<typename Enum> void testVariantMeta(Enum value, bool *ok, const char *string)
4829{
4830 testVariant<Enum>(value, ok);
4831 QVERIFY(ok);
4832 *ok = false;
4833
4834 QVariant var = QVariant::fromValue(value);
4835 QVERIFY(var.canConvert<QString>());
4836 QVERIFY(var.canConvert<QByteArray>());
4837
4838 QCOMPARE(var.value<QString>(), QString::fromLatin1(string));
4839 QCOMPARE(var.value<QByteArray>(), QByteArray(string));
4840
4841 QVariant strVar = QString::fromLatin1(str: string);
4842 QVERIFY(strVar.canConvert<Enum>());
4843 if ((static_cast<qint64>(value) > INT_MAX) || (static_cast<qint64>(value) < INT_MIN)) {
4844 QEXPECT_FAIL("", "QMetaEnum api uses 'int' as return type QTBUG-27451", Abort);
4845 *ok = true;
4846 }
4847 QCOMPARE(strVar.value<Enum>(), value);
4848 strVar = QByteArray(string);
4849 QVERIFY(strVar.canConvert<Enum>());
4850 QCOMPARE(strVar.value<Enum>(), value);
4851 *ok = true;
4852}
4853
4854void tst_QVariant::metaEnums()
4855{
4856 bool ok = false;
4857#define METAENUMS_TEST(Value) \
4858 testVariantMeta(Value, &ok, #Value); QVERIFY(ok)
4859
4860 METAENUMS_TEST(MetaEnumTest_Enum0_value);
4861 METAENUMS_TEST(MetaEnumTest_Enum1_value);
4862 METAENUMS_TEST(MetaEnumTest_Enum1_bigValue);
4863 METAENUMS_TEST(MetaEnumTest_Enum3_value);
4864 METAENUMS_TEST(MetaEnumTest_Enum3_bigValue);
4865 METAENUMS_TEST(MetaEnumTest_Enum3_bigNegValue);
4866 METAENUMS_TEST(MetaEnumTest_Enum4_value);
4867 METAENUMS_TEST(MetaEnumTest_Enum4_bigValue);
4868 METAENUMS_TEST(MetaEnumTest_Enum5_value);
4869 METAENUMS_TEST(MetaEnumTest_Enum6_value);
4870 METAENUMS_TEST(MetaEnumTest_Enum8_value);
4871}
4872
4873void tst_QVariant::compareSanity_data()
4874{
4875 QTest::addColumn<QVariant>(name: "value1");
4876 QTest::addColumn<QVariant>(name: "value2");
4877
4878 QTest::newRow( dataTag: "int <>/== QUrl" ) << QVariant( 97 ) << QVariant(QUrl("a"));
4879 QTest::newRow( dataTag: "int <>/== QChar" ) << QVariant( 97 ) << QVariant(QChar('a'));
4880 QTest::newRow( dataTag: "int <>/== QString" ) << QVariant( 97 ) << QVariant(QString("a"));
4881 QTest::newRow( dataTag: "QUrl <>/== QChar" ) << QVariant(QUrl("a")) << QVariant(QChar('a'));
4882 QTest::newRow( dataTag: "QUrl <>/== QString" ) << QVariant(QUrl("a")) << QVariant(QString("a"));
4883 QTest::newRow( dataTag: "QChar <>/== QString" ) << QVariant(QChar('a')) << QVariant(QString("a"));
4884}
4885
4886void tst_QVariant::compareSanity()
4887{
4888 QFETCH(QVariant, value1);
4889 QFETCH(QVariant, value2);
4890
4891 if (value1 == value2) {
4892 QVERIFY(!(value1 < value2) && !(value1 > value2));
4893 } else {
4894 QVERIFY(value1 != value2);
4895 QVERIFY((value1 < value2) || (value1 > value2));
4896 }
4897}
4898
4899static void richComparison(const QVariant& less, const QVariant& more)
4900{
4901 QVERIFY(less.type() == more.type());
4902
4903 QVERIFY(less < more);
4904 QVERIFY(!(more < less));
4905
4906 QVERIFY(more > less);
4907 QVERIFY(!(less > more));
4908
4909 QVERIFY(less <= more);
4910 QVERIFY(!(more <= less));
4911 QVERIFY(less <= less);
4912
4913 QVERIFY(more >= less);
4914 QVERIFY(!(less >= more));
4915 QVERIFY(more >= more);
4916}
4917
4918void tst_QVariant::compareRich()
4919{
4920 richComparison(less: QUuid("{49d8ad2a-2ee8-4c3d-949f-1b5a3765ddf0}"),
4921 more: QUuid("{f6d56824-16e9-4543-a375-add2877c2d05}"));
4922 richComparison(less: QByteArray::fromRawData("a", size: 1),
4923 more: QByteArray::fromRawData("b", size: 1));
4924 richComparison(QStringLiteral("a"), QStringLiteral("b"));
4925 richComparison(less: QLatin1String("a"), more: QLatin1String("b"));
4926 richComparison(less: QChar('a'), more: QChar('b'));
4927 richComparison(less: QDate(2016, 7, 23), more: QDate(2016, 7, 24));
4928 richComparison(less: QTime(0, 0), more: QTime(0, 1));
4929 richComparison(less: QDateTime(QDate(2016, 7, 23), QTime(0, 0)),
4930 more: QDateTime(QDate(2016, 7, 23), QTime(0, 1)));
4931
4932 richComparison(less: QStringList(), more: QStringList() << QStringLiteral("a"));
4933 richComparison(less: QStringList(), more: QStringList() << QStringLiteral("a")
4934 << QStringLiteral("b"));
4935 richComparison(less: QStringList() << QStringLiteral("a"),
4936 more: QStringList() << QStringLiteral("b"));
4937 richComparison(less: QStringList() << QStringLiteral("a"),
4938 more: QStringList() << QStringLiteral("b")
4939 << QStringLiteral("c"));
4940 richComparison(less: QStringList() << QStringLiteral("a")
4941 << QStringLiteral("c"),
4942 more: QStringList() << QStringLiteral("b"));
4943 richComparison(less: QStringList() << QStringLiteral("a")
4944 << QStringLiteral("c"),
4945 more: QStringList() << QStringLiteral("b")
4946 << QStringLiteral("d"));
4947 richComparison(less: QStringList() << QStringLiteral("a")
4948 << QStringLiteral("c"),
4949 more: QStringList() << QStringLiteral("a")
4950 << QStringLiteral("d"));
4951}
4952
4953void tst_QVariant::nullConvert()
4954{
4955 // Test quirks with QVariants different types of null states.
4956
4957 // null variant with no initialized value
4958 QVariant nullVar(QVariant::String);
4959 QVERIFY(nullVar.isValid());
4960 QVERIFY(nullVar.isNull());
4961 // We can not convert a variant with no value
4962 QVERIFY(!nullVar.convert(QVariant::Url));
4963 QCOMPARE(nullVar.type(), QVariant::Url);
4964 QVERIFY(nullVar.isNull());
4965
4966 // variant initialized with null value
4967 QVariant nullStr = QVariant::fromValue(value: QString());
4968 QVERIFY(nullStr.isValid());
4969 QVERIFY(nullStr.isNull());
4970 // We can convert an initialized null value however
4971 QVERIFY(nullStr.convert(QVariant::Url));
4972 QCOMPARE(nullStr.type(), QVariant::Url);
4973 QVERIFY(nullStr.isValid());
4974 // QUrl does not have an isNull method
4975 QVERIFY(!nullStr.isNull());
4976 // The URL is not valid however
4977 QVERIFY(!nullStr.toUrl().isValid());
4978}
4979
4980void tst_QVariant::accessSequentialContainerKey()
4981{
4982 QString nameResult;
4983
4984 {
4985 QMap<QString, QObject*> mapping;
4986 QString name = QString::fromLatin1(str: "Seven");
4987 mapping.insert(akey: name, avalue: nullptr);
4988
4989 QVariant variant = QVariant::fromValue(value: mapping);
4990
4991 QAssociativeIterable iterable = variant.value<QAssociativeIterable>();
4992 QAssociativeIterable::const_iterator iit = iterable.begin();
4993 const QAssociativeIterable::const_iterator end = iterable.end();
4994 for ( ; iit != end; ++iit) {
4995 nameResult += iit.key().toString();
4996 }
4997 } // Destroy mapping
4998 // Regression test for QTBUG-52246 - no memory corruption/double deletion
4999 // of the string key.
5000
5001 QCOMPARE(nameResult, QStringLiteral("Seven"));
5002}
5003
5004void tst_QVariant::shouldDeleteVariantDataWorksForSequential()
5005{
5006 QCOMPARE(instanceCount, 0);
5007 {
5008 QtMetaTypePrivate::QSequentialIterableImpl iterator {};
5009 iterator._iteratorCapabilities = QtMetaTypePrivate::RandomAccessCapability |
5010 QtMetaTypePrivate::BiDirectionalCapability |
5011 QtMetaTypePrivate::ForwardCapability;
5012 iterator._metaType_flags = QVariantConstructionFlags::ShouldDeleteVariantData;
5013
5014 iterator._size = [](const void *) {return 1;};
5015 iterator._metaType_id = qMetaTypeId<MyType>();
5016 iterator._moveToBegin = [](const void *, void **) {};
5017 iterator._moveToEnd = [](const void *, void **) {};
5018 iterator._advance = [](void **, int) {};
5019 iterator._destroyIter = [](void **){};
5020 iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
5021 iterator._destroyIter = [](void **){};
5022 iterator._at = [](const void *, int ) -> void const * {
5023 MyType mytype {1, "eins"};
5024 return QMetaType::create(type: qMetaTypeId<MyType>(), copy: &mytype);
5025 };
5026 iterator._get = [](void * const *, int, uint) -> QtMetaTypePrivate::VariantData {
5027 MyType mytype {2, "zwei"};
5028 return {qMetaTypeId<MyType>(), QMetaType::create(type: qMetaTypeId<MyType>(), copy: &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
5029 };
5030 QSequentialIterable iterable {iterator};
5031 QVariant value1 = iterable.at(idx: 0);
5032 QVERIFY(value1.canConvert<MyType>());
5033 QCOMPARE(value1.value<MyType>().number, 1);
5034 QVariant value2 = *iterable.begin();
5035 QVERIFY(value2.canConvert<MyType>());
5036 QCOMPARE(value2.value<MyType>().number, 2);
5037 }
5038 QCOMPARE(instanceCount, 0);
5039}
5040
5041void tst_QVariant::shouldDeleteVariantDataWorksForAssociative()
5042{
5043 QCOMPARE(instanceCount, 0);
5044 {
5045 QtMetaTypePrivate::QAssociativeIterableImpl iterator {};
5046 iterator._metaType_flags_key = QVariantConstructionFlags::ShouldDeleteVariantData;
5047 iterator._metaType_flags_value = QVariantConstructionFlags::ShouldDeleteVariantData;
5048
5049 iterator._size = [](const void *) {return 1;};
5050 iterator._metaType_id_value = qMetaTypeId<MyType>();
5051 iterator._metaType_id_key = qMetaTypeId<MyType>();
5052 iterator._begin = [](const void *, void **) {};
5053 iterator._end = [](const void *, void **) {};
5054 iterator._advance = [](void **, int) {};
5055 iterator._destroyIter = [](void **){};
5056 iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
5057 iterator._destroyIter = [](void **){};
5058 iterator._find = [](const void *, const void *, void **iterator ) -> void {
5059 (*iterator) = reinterpret_cast<void *>(quintptr(42));
5060 };
5061 iterator._getKey = [](void * const *iterator, int, uint) -> QtMetaTypePrivate::VariantData {
5062 MyType mytype {1, "key"};
5063 if (reinterpret_cast<quintptr>(*iterator) == 42) {
5064 mytype.number = 42;
5065 mytype.text = "find_key";
5066 }
5067 return {qMetaTypeId<MyType>(), QMetaType::create(type: qMetaTypeId<MyType>(), copy: &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
5068 };
5069 iterator._getValue = [](void * const *iterator, int, uint) -> QtMetaTypePrivate::VariantData {
5070 MyType mytype {2, "value"};
5071 if (reinterpret_cast<quintptr>(*iterator) == 42) {
5072 mytype.number = 42;
5073 mytype.text = "find_value";
5074 }
5075 return {qMetaTypeId<MyType>(), QMetaType::create(type: qMetaTypeId<MyType>(), copy: &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
5076 };
5077 QAssociativeIterable iterable {iterator};
5078 auto it = iterable.begin();
5079 QVariant value1 = it.key();
5080 QVERIFY(value1.canConvert<MyType>());
5081 QCOMPARE(value1.value<MyType>().number, 1);
5082 QCOMPARE(value1.value<MyType>().text, "key");
5083 QVariant value2 = it.value();
5084 QVERIFY(value2.canConvert<MyType>());
5085 QCOMPARE(value2.value<MyType>().number, 2);
5086 auto findIt = iterable.find(key: QVariant::fromValue(value: MyType {}));
5087 value1 = findIt.key();
5088 QCOMPARE(value1.value<MyType>().number, 42);
5089 QCOMPARE(value1.value<MyType>().text, "find_key");
5090 value2 = findIt.value();
5091 QCOMPARE(value2.value<MyType>().number, 42);
5092 QCOMPARE(value2.value<MyType>().text, "find_value");
5093 }
5094 QCOMPARE(instanceCount, 0);
5095}
5096
5097void tst_QVariant::fromStdVariant()
5098{
5099#if __has_include(<variant>) && __cplusplus >= 201703L
5100 {
5101 typedef std::variant<int, bool> intorbool_t;
5102 intorbool_t stdvar = 5;
5103 QVariant qvar = QVariant::fromStdVariant(value: stdvar);
5104 QVERIFY(!qvar.isNull());
5105 QCOMPARE(qvar.type(), QVariant::Int);
5106 QCOMPARE(qvar.value<int>(), std::get<int>(stdvar));
5107 stdvar = true;
5108 qvar = QVariant::fromStdVariant(value: stdvar);
5109 QVERIFY(!qvar.isNull());
5110 QCOMPARE(qvar.type(), QVariant::Bool);
5111 QCOMPARE(qvar.value<bool>(), std::get<bool>(stdvar));
5112 }
5113 {
5114 std::variant<std::monostate, int> stdvar;
5115 QVariant qvar = QVariant::fromStdVariant(value: stdvar);
5116 QVERIFY(!qvar.isValid());
5117 stdvar = -4;
5118 qvar = QVariant::fromStdVariant(value: stdvar);
5119 QVERIFY(!qvar.isNull());
5120 QCOMPARE(qvar.type(), QVariant::Int);
5121 QCOMPARE(qvar.value<int>(), std::get<int>(stdvar));
5122 }
5123 {
5124 std::variant<int, bool, QChar> stdvar = QChar::fromLatin1(c: ' ');
5125 QVariant qvar = QVariant::fromStdVariant(value: stdvar);
5126 QVERIFY(!qvar.isNull());
5127 QCOMPARE(qvar.type(), QVariant::Char);
5128 QCOMPARE(qvar.value<QChar>(), std::get<QChar>(stdvar));
5129 }
5130#endif
5131}
5132
5133void tst_QVariant::qt4UuidDataStream()
5134{
5135 qRegisterMetaTypeStreamOperators<QUuid>();
5136
5137 QByteArray data;
5138 QDataStream stream(&data, QIODevice::WriteOnly);
5139 stream.setVersion(QDataStream::Qt_4_8);
5140 QUuid source(0x12345678,0x1234,0x1234,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89);
5141 stream << QVariant::fromValue(value: source);
5142 const QByteArray qt4Data = QByteArray::fromHex(hexEncoded: "0000007f000000000651557569640012345678123412341223344556677889");
5143 QCOMPARE(data, qt4Data);
5144
5145 QDataStream input(&data, QIODevice::ReadOnly);
5146 input.setVersion(QDataStream::Qt_4_8);
5147 QVariant result;
5148 input >> result;
5149 QCOMPARE(result.value<QUuid>(), source);
5150}
5151
5152void tst_QVariant::sequentialIterableEndianessSanityCheck()
5153{
5154 namespace QMTP = QtMetaTypePrivate;
5155 uint oldIteratorCaps = QMTP::ForwardCapability | QMTP::BiDirectionalCapability | QMTP::RandomAccessCapability;
5156 QMTP::QSequentialIterableImpl seqImpl {};
5157 QCOMPARE(seqImpl.revision(), 1u);
5158 memcpy(dest: &seqImpl._iteratorCapabilities, src: &oldIteratorCaps, n: sizeof(oldIteratorCaps));
5159 QCOMPARE(seqImpl.revision(), 0u);
5160}
5161
5162void tst_QVariant::sequentialIterableAppend()
5163{
5164 {
5165 QVector<int> container {1, 2};
5166 auto variant = QVariant::fromValue(value: container);
5167 QVERIFY(variant.canConvert<QtMetaTypePrivate::QSequentialIterableImpl>());
5168 auto asIterable = variant.value<QtMetaTypePrivate::QSequentialIterableImpl>();
5169 const int i = 3, j = 4;
5170 asIterable.append(newElement: &i);
5171 asIterable.append(newElement: &j);
5172 QCOMPARE(variant.value<QVector<int>>(), QVector<int> ({1, 2, 3, 4}));
5173 }
5174 {
5175 QSet<QByteArray> container { QByteArray{"hello"}, QByteArray{"world"} };
5176 auto variant = QVariant::fromValue(value: std::move(container));
5177 QVERIFY(variant.canConvert<QtMetaTypePrivate::QSequentialIterableImpl>());
5178 auto asIterable = variant.value<QtMetaTypePrivate::QSequentialIterableImpl>();
5179 QByteArray qba1 {"goodbye"};
5180 QByteArray qba2 { "moon" };
5181 asIterable.append( newElement: &qba1 );
5182 asIterable.append( newElement: &qba2);
5183 QSet<QByteArray> reference { "hello", "world", "goodbye", "moon" };
5184 QCOMPARE(variant.value<QSet<QByteArray>>(), reference);
5185 }
5186}
5187
5188void tst_QVariant::preferDirectConversionOverInterfaces()
5189{
5190 using namespace QtMetaTypePrivate;
5191 bool calledCorrectConverter = false;
5192 QMetaType::registerConverter<MyType, QSequentialIterableImpl>(function: [](const MyType &) {
5193 return QSequentialIterableImpl {};
5194 });
5195 QMetaType::registerConverter<MyType, QVariantList>(function: [&calledCorrectConverter](const MyType &) {
5196 calledCorrectConverter = true;
5197 return QVariantList {};
5198 });
5199 QMetaType::registerConverter<MyType, QAssociativeIterableImpl>(function: [](const MyType &) {
5200 return QAssociativeIterableImpl {};
5201 });
5202 QMetaType::registerConverter<MyType, QVariantHash>(function: [&calledCorrectConverter](const MyType &) {
5203 calledCorrectConverter = true;
5204 return QVariantHash {};
5205 });
5206 QMetaType::registerConverter<MyType, QVariantMap>(function: [&calledCorrectConverter](const MyType &) {
5207 calledCorrectConverter = true;
5208 return QVariantMap {};
5209 });
5210 auto holder = QVariant::fromValue(value: MyType {});
5211
5212 QVERIFY(holder.canConvert<QSequentialIterableImpl>());
5213 QVERIFY(holder.canConvert<QVariantList>());
5214 QVERIFY(holder.canConvert<QAssociativeIterableImpl>());
5215 QVERIFY(holder.canConvert<QVariantHash>());
5216 QVERIFY(holder.canConvert<QVariantMap>());
5217
5218 holder.value<QVariantList>();
5219 QVERIFY(calledCorrectConverter);
5220 calledCorrectConverter = false;
5221
5222 holder.value<QVariantHash>();
5223 QVERIFY(calledCorrectConverter);
5224 calledCorrectConverter = false;
5225
5226 holder.value<QVariantMap>();
5227 QVERIFY(calledCorrectConverter);
5228}
5229
5230QTEST_MAIN(tst_QVariant)
5231#include "tst_qvariant.moc"
5232

source code of qtbase/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp