diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index a36f5c6fc80..0967bdb9470 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -215,6 +215,24 @@ private slots: void toBool_data(); void toBool(); + void toSChar_data(); + void toSChar(); + + void toUChar_data(); + void toUChar(); + + void toShort_data(); + void toShort(); + + void toUShort_data(); + void toUShort(); + + void toLong_data(); + void toLong(); + + void toULong_data(); + void toULong(); + void toLongLong_data(); void toLongLong(); @@ -829,47 +847,92 @@ void tst_QVariant::convert() QCOMPARE(var.toInt(), 0); } -void tst_QVariant::toInt_data() +template static void addNumberConversionHelper(From v) +{ + if constexpr (std::is_same_v) + return; + + To to = To(v); + QVariant var = QVariant::fromValue(v); + + // std::numeric_limits is specialized for qfloat16, std::is_floating_point isn't. + if constexpr (std::numeric_limits::is_iec559 && std::is_unsigned_v) { + using STo = std::make_signed_t; + STo s = STo(v); + Q_ASSERT(v < 0); + Q_ASSERT(s < 0); + QTest::addRow("negative-%s", var.typeName()) << var << To(s) << true; + + v = -v; + to = To(v); + var = QVariant::fromValue(v); + } + QTest::addRow("%s", var.typeName()) << var << to << true; +} + +template static void addNumberConversions() { QTest::addColumn("value"); - QTest::addColumn("result"); + QTest::addColumn("result"); QTest::addColumn("valueOK"); - QTest::newRow( "invalid" ) << QVariant() << 0 << false; - QTest::newRow( "int" ) << QVariant( 123 ) << 123 << true; - QTest::newRow( "char" ) << QVariant::fromValue('a') << int('a') << true; - signed char signedChar = -13; - QTest::newRow( "signed char" ) << QVariant::fromValue(signedChar) << -13 << true; - QTest::newRow( "short" ) << QVariant::fromValue(short(-7)) << int(-7) << true; - QTest::newRow( "ushort" ) << QVariant::fromValue(ushort(30000)) << 30000 << true; - QTest::newRow( "double" ) << QVariant( 3.1415927 ) << 3 << true; - QTest::newRow( "float" ) << QVariant( 3.1415927f ) << 3 << true; - QTest::newRow( "uint" ) << QVariant( 123u ) << 123 << true; - QTest::newRow( "int-string" ) << QVariant( QString("123") ) << 123 << true; - QTest::newRow( "string" ) << QVariant( QString("Unicode String") ) << 0 << false; - QTest::newRow( "longlong0" ) << QVariant( (qlonglong)34 ) << 34 << true; - QTest::newRow( "longlong1" ) << QVariant( intMax1 ) << (int)INT_MIN << true; - QTest::newRow( "ulonglong0" ) << QVariant( (qulonglong)34 ) << 34 << true; - QTest::newRow( "ulonglong1" ) << QVariant( uintMax1 ) << 0 << true; - QTest::newRow( "signedint" ) << QVariant( -123 ) << -123 << true; - QTest::newRow( "signeddouble" ) << QVariant( -3.1415927 ) << -3 << true; - QTest::newRow( "signedfloat" ) << QVariant( -3.1415927f ) << -3 << true; - QTest::newRow( "signedint-string" ) << QVariant( QString("-123") ) << -123 << true; - QTest::newRow( "signedlonglong0" ) << QVariant( (qlonglong)-34 ) << -34 << true; - QTest::newRow( "QChar" ) << QVariant(QChar('a')) << int('a') << true; - QByteArray bytearray(4, ' '); - bytearray[0] = 'T'; - bytearray[1] = 'e'; - bytearray[2] = 's'; - bytearray[3] = 't'; - QTest::newRow( "QByteArray1" ) << QVariant( bytearray ) << 0 << false; - bytearray[0] = '4'; - bytearray[1] = '5'; - bytearray[2] = '0'; - bytearray[3] = '0'; - QTest::newRow( "QByteArray2" ) << QVariant( bytearray ) << 4500 << true; - QTest::newRow("int-QJsonValue") << QVariant(QJsonValue(321)) << 321 << true; - QTest::newRow("undefined-QJsonValue") << QVariant(QJsonValue(QJsonValue::Undefined)) << 0 << false; + QTest::newRow("invalid") << QVariant() << To{} << false; + + auto addNumber = [](auto v) { addNumberConversionHelper(v); }; + addNumber(true); + addNumber(char(1)); + addNumber(qint8(-1)); + addNumber(quint8(2)); + // addNumber(u'A'); + addNumber(short(-256)); + addNumber(ushort(256)); + // addNumber(U'\U00010000'); + addNumber(-65536); + addNumber(65536U); + addNumber(-0x8000'0000L); + addNumber(0x8000'0000UL); + addNumber(-0x1'0000'0000LL); + addNumber(0x1'0000'000'0000ULL); + addNumber(-3.1415927f); + addNumber(-3.1415927); + + if constexpr (sizeof(To) > sizeof(int)) { + // note: this includes double + qint64 value64 = (Q_INT64_C(12) << 35) + 8; + QTest::newRow("qint64") << QVariant::fromValue(value64) << To(value64) << true; + QTest::newRow("-qint64") << QVariant::fromValue(-value64) << To(-value64) << true; + QTest::newRow("LONG_MIN") << QVariant::fromValue(LONG_MIN) << To(LONG_MIN) << true; + QTest::newRow("-LONG_MIN/2") << QVariant::fromValue(-(LONG_MIN / 2)) << -To(LONG_MIN/2) << true; + + if constexpr (std::is_integral_v) { + QTest::newRow("LONG_MAX") << QVariant::fromValue(LONG_MAX) << To(LONG_MAX) << true; + QTest::newRow("ULONG_MAX") << QVariant::fromValue(ULONG_MAX) << To(ULONG_MAX) << true; + } + } + + if constexpr (std::is_integral_v) + QTest::newRow("QChar") << QVariant(QChar('a')) << To('a') << true; + QTest::newRow("nonint-QByteArray") << QVariant(QByteArray("zzzz")) << To{} << false; + QTest::newRow("nonint-QString") << QVariant(QString("zzzz")) << To{} << false; + QTest::newRow("undefined-QCborValue") << QVariant::fromValue({}) << To{} << false; + QTest::newRow("undefined-QJsonValue") << QVariant(QJsonValue()) << To{} << false; + + QTest::newRow("int-QByteArray") << QVariant(QByteArray("123")) << To(123) << true; + QTest::newRow("int-QCborValue") << QVariant::fromValue(QCborValue(321)) << To(321) << true; + QTest::newRow("int-QJsonValue") << QVariant(QJsonValue(321)) << To(321) << true; + QTest::newRow("int-QString") << QVariant(QString("123")) << To(123) << true; + + if constexpr (std::numeric_limits::is_iec559) { + QTest::newRow("fp-QByteArray") << QVariant(QByteArray("32.1")) << To(32.1) << true; + QTest::newRow("fp-QCborValue") << QVariant::fromValue(QCborValue(32.1)) << To(32.1) << true; + QTest::newRow("fp-QJsonValue") << QVariant(QJsonValue(32.1)) << To(32.1) << true; + QTest::newRow("fp-QString") << QVariant(QString("32.1")) << To(32.1) << true; + } +} + +void tst_QVariant::toInt_data() +{ + addNumberConversions(); } #if QT_DEPRECATED_SINCE(6, 0) @@ -878,71 +941,47 @@ void tst_QVariant::toInt_data() # define EXEC_DEPRECATED_CALL(x) #endif -void tst_QVariant::toInt() +template static void checkNumberConversions(T (QVariant:: *toType)(bool *) const = nullptr) { QFETCH( QVariant, value ); - QFETCH( int, result ); + QFETCH( T, result ); QFETCH( bool, valueOK ); - EXEC_DEPRECATED_CALL(QVERIFY( value.isValid() == value.canConvert( QVariant::Int ) );) - QVERIFY( value.isValid() == value.canConvert(QMetaType::fromType()) ); - bool ok; - int i = value.toInt( &ok ); - QCOMPARE( i, result ); - QVERIFY( ok == valueOK ); + + QMetaType mt = QMetaType::fromType(); + int typeId = mt.id(); + EXEC_DEPRECATED_CALL(QVERIFY(value.isValid() == value.canConvert(typeId));) + QCOMPARE(value.isValid(), value.canConvert(mt)); + + if (toType) { + // QVariant conversion API + bool ok; + T i = (value.*toType)(&ok); + QCOMPARE(i, result); + QVERIFY(ok == valueOK); + } + + if (value.isValid()) { + // test the conversion API (through QMetaType) + QCOMPARE(value.convert(mt), valueOK); + QCOMPARE(qvariant_cast(value), result); + } +} + +void tst_QVariant::toInt() +{ + checkNumberConversions(&QVariant::toInt); } void tst_QVariant::toUInt_data() { - QTest::addColumn("value"); - QTest::addColumn("result"); - QTest::addColumn("valueOK"); - - QTest::newRow( "int" ) << QVariant( 123 ) << (uint)123 << true; - QTest::newRow( "char" ) << QVariant::fromValue('a') << uint('a') << true; - signed char signedChar = 12; - QTest::newRow( "signed char" ) << QVariant::fromValue(signedChar) << uint(12) << true; - QTest::newRow( "double" ) << QVariant( 3.1415927 ) << (uint)3 << true; - QTest::newRow( "float" ) << QVariant( 3.1415927f ) << (uint)3 << true; - QTest::newRow( "uint" ) << QVariant( 123u ) << (uint)123 << true; - QTest::newRow( "int-string" ) << QVariant( QString("123") ) << (uint)123 << true; - QTest::newRow( "string" ) << QVariant( QString("Unicode String") ) << (uint)0 << false; - QTest::newRow( "string2" ) << QVariant( QString("4") ) << (uint)4 << true; - QTest::newRow( "longlong0" ) << QVariant( (qlonglong)34 ) << (uint)34 << true; - QTest::newRow( "longlong1" ) << QVariant( intMax1 ) << (uint)INT_MIN << true; - QTest::newRow( "ulonglong0" ) << QVariant( (qulonglong)34 ) << (uint)34 << true; - QTest::newRow( "ulonglong1" ) << QVariant( uintMax1 ) << (uint)0 << true; - QTest::newRow( "negativeint" ) << QVariant( -123 ) << (uint)-123 << true; - QTest::newRow( "negativedouble" ) << QVariant( -3.1415927 ) << (uint)-3 << true; - QTest::newRow( "negativefloat" ) << QVariant( -3.1415927f ) << (uint)-3 << true; - QTest::newRow( "negativeint-string" ) << QVariant( QString("-123") ) << (uint)0 << false; - QTest::newRow( "negativelonglong0" ) << QVariant( (qlonglong)-34 ) << (uint)-34 << true; - QTest::newRow( "QChar" ) << QVariant(QChar('a')) << uint('a') << true; - QByteArray bytearray(4, ' '); - bytearray[0] = '4'; - bytearray[1] = '3'; - bytearray[2] = '2'; - bytearray[3] = '1'; - QTest::newRow( "QByteArray" ) << QVariant( bytearray ) << (uint)4321 << true; - QTest::newRow("int-QJsonValue") << QVariant(QJsonValue(321)) << (uint)321 << true; - QTest::newRow("null-QJsonValue") << QVariant(QJsonValue(QJsonValue::Null)) << (uint)0 << false; + addNumberConversions(); } void tst_QVariant::toUInt() { - QFETCH( QVariant, value ); - QFETCH( uint, result ); - QFETCH( bool, valueOK ); - QVERIFY( value.isValid() ); - EXEC_DEPRECATED_CALL(QVERIFY( value.canConvert( QVariant::UInt ) );) - QVERIFY( value.canConvert(QMetaType::fromType()) ); - - bool ok; - uint i = value.toUInt( &ok ); - QVERIFY( ok == valueOK ); - QCOMPARE( i, result ); + checkNumberConversions(&QVariant::toUInt); } - void tst_QVariant::toSize_data() { QTest::addColumn("value"); @@ -1120,6 +1159,8 @@ void tst_QVariant::toBool_data() QTest::newRow( "Null_QChar" ) << QVariant(QChar(0)) << false; QTest::newRow("QJsonValue(true)") << QVariant(QJsonValue(true)) << true; QTest::newRow("QJsonValue(false)") << QVariant(QJsonValue(false)) << false; + QTest::newRow("QCborValue(true)") << QVariant::fromValue(QCborValue(true)) << true; + QTest::newRow("QCborValue(false)") << QVariant::fromValue(QCborValue(false)) << false; } void tst_QVariant::toBool() @@ -1132,6 +1173,9 @@ void tst_QVariant::toBool() bool i = value.toBool(); QCOMPARE( i, result ); + + QVERIFY(value.convert(QMetaType::fromType())); + QCOMPARE(value.toBool(), result); } void tst_QVariant::toPointF_data() @@ -1176,170 +1220,103 @@ void tst_QVariant::toRectF() void tst_QVariant::toDouble_data() { - QTest::addColumn("value"); - QTest::addColumn("result"); - QTest::addColumn("valueOK"); - - QByteArray bytearray(4, ' '); - bytearray[0] = '3'; - bytearray[1] = '2'; - bytearray[2] = '.'; - bytearray[3] = '1'; - QTest::newRow( "bytearray" ) << QVariant( bytearray ) << 32.1 << true; - QTest::newRow("double-QJsonValue") << QVariant(QJsonValue(32.1)) << 32.1 << true; - QTest::newRow("null-QJsonValue") << QVariant(QJsonValue(QJsonValue::Null)) << 0.0 << false; + addNumberConversions(); } void tst_QVariant::toDouble() { - QFETCH( QVariant, value ); - QFETCH( double, result ); - QFETCH( bool, valueOK ); - QVERIFY( value.isValid() ); - EXEC_DEPRECATED_CALL(QVERIFY( value.canConvert( QVariant::Double ) );) - QVERIFY( value.canConvert(QMetaType::fromType()) ); - bool ok; - double d = value.toDouble( &ok ); - QCOMPARE( d, result ); - QVERIFY( ok == valueOK ); + checkNumberConversions(&QVariant::toDouble); } void tst_QVariant::toFloat_data() { - QTest::addColumn("value"); - QTest::addColumn("result"); - QTest::addColumn("valueOK"); - - QByteArray bytearray(4, ' '); - bytearray[0] = '3'; - bytearray[1] = '2'; - bytearray[2] = '.'; - bytearray[3] = '1'; - QTest::newRow("QByteArray") << QVariant(bytearray) << float(32.1) << true; - QTest::newRow("double-QJsonValue") << QVariant(QJsonValue(32.1)) << float(32.1) << true; - QTest::newRow("undefined-QJsonValue") << QVariant(QJsonValue(QJsonValue::Undefined)) << float(0.0) << false; + addNumberConversions(); } void tst_QVariant::toFloat() { - QFETCH(QVariant, value ); - QFETCH(float, result); - QFETCH(bool, valueOK); - QVERIFY(value.isValid()); - EXEC_DEPRECATED_CALL(QVERIFY(value.canConvert(QMetaType::Float));) - QVERIFY(value.canConvert(QMetaType::fromType())); - bool ok; - float d = value.toFloat(&ok); - QCOMPARE(d, result); - QCOMPARE(ok, valueOK); + checkNumberConversions(&QVariant::toFloat); +} + +void tst_QVariant::toSChar_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toSChar() +{ + checkNumberConversions(); +} + +void tst_QVariant::toUChar_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toUChar() +{ + checkNumberConversions(); +} + +void tst_QVariant::toShort_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toShort() +{ + checkNumberConversions(); +} + +void tst_QVariant::toUShort_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toUShort() +{ + checkNumberConversions(); +} + +void tst_QVariant::toLong_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toLong() +{ + checkNumberConversions(); +} + +void tst_QVariant::toULong_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toULong() +{ + checkNumberConversions(); } void tst_QVariant::toLongLong_data() { - QTest::addColumn("value"); - QTest::addColumn("result"); - QTest::addColumn("valueOK"); + addNumberConversions(); - QTest::newRow( "int0" ) << QVariant( 123 ) << (qlonglong)123 << true; - QTest::newRow( "double" ) << QVariant( 3.1415927 ) << (qlonglong)3 << true; - QTest::newRow( "float" ) << QVariant( 3.1415927f ) << (qlonglong)3 << true; - QTest::newRow( "uint" ) << QVariant( 123u ) << (qlonglong)123 << true; - QTest::newRow( "int-string" ) << QVariant( QString("123") ) - << (qlonglong)123 << true; - QTest::newRow( "string" ) << QVariant( QString("Unicode fun") ) << (qlonglong)0 - << false; - QTest::newRow( "longlong" ) << QVariant( intMax1 ) << intMax1 << true; - QTest::newRow( "ulonglong" ) << QVariant( uintMax1 ) << (qlonglong)uintMax1 << true; - QTest::newRow( "QChar" ) << QVariant(QChar('a')) << qlonglong('a') << true; - QByteArray bytearray(4, ' '); - bytearray[0] = '3'; - bytearray[1] = '2'; - bytearray[2] = '0'; - bytearray[3] = '0'; - QTest::newRow( "QByteArray" ) << QVariant( bytearray ) << (qlonglong) 3200 << true; - QTest::newRow("int-QJsonValue") << QVariant(QJsonValue(321)) << (qlonglong)321 << true; - QTest::newRow("string-QJsonValue") << QVariant(QJsonValue(QString("string"))) << (qlonglong)0 << false; - - qint64 value64 = (Q_INT64_C(12) << 35) + 8; - QTest::newRow("qint64") << QVariant::fromValue(value64) << qlonglong(value64) << true; - QTest::newRow("-qint64") << QVariant::fromValue(-value64) << qlonglong(-value64) << true; - QTest::newRow("long") << QVariant::fromValue(long(464646)) << qlonglong(464646) << true; - QTest::newRow("LONG_MAX") << QVariant::fromValue( LONG_MAX ) << qlonglong(LONG_MAX) << true; - QTest::newRow("LONG_MIN") << QVariant::fromValue( LONG_MIN ) << qlonglong(LONG_MIN) << true; - - QTest::newRow( "short" ) << QVariant(short(12)) << qlonglong(12) << true; - QTest::newRow( "-short" ) << QVariant(short(-24)) << qlonglong(-24) << true; - QTest::newRow( "ushort" ) << QVariant(ushort(15)) << qlonglong(15) << true; } void tst_QVariant::toLongLong() { - QFETCH( QVariant, value ); - QFETCH( qlonglong, result ); - QFETCH( bool, valueOK ); - QVERIFY( value.isValid() ); - EXEC_DEPRECATED_CALL(QVERIFY( value.canConvert( QVariant::LongLong ) );) - QVERIFY( value.canConvert(QMetaType::fromType()) ); - bool ok; - qlonglong ll = value.toLongLong( &ok ); - QCOMPARE( ll, result ); - QVERIFY( ok == valueOK ); + checkNumberConversions(&QVariant::toLongLong); } void tst_QVariant::toULongLong_data() { - QTest::addColumn("value"); - QTest::addColumn("result"); - QTest::addColumn("valueOK"); - - QTest::newRow( "int0" ) << QVariant( 123 ) << (qulonglong)123 << true; - QTest::newRow( "double" ) << QVariant( 3.1415927 ) << (qulonglong)3 << true; - QTest::newRow( "float" ) << QVariant( 3.1415927f ) << (qulonglong)3 << true; - QTest::newRow( "uint" ) << QVariant( 123u ) << (qulonglong)123 << true; - QTest::newRow( "int-string" ) << QVariant( QString("123") ) - << (qulonglong)123 << true; - QTest::newRow( "string" ) << QVariant( QString("Unicode fun") ) << (qulonglong)0 - << false; - QTest::newRow( "ulonglong-string" ) << QVariant( QString("18446744073709551615") ) - << Q_UINT64_C(18446744073709551615) - << true; - QTest::newRow( "bytaa-string" ) << QVariant( QString("18446744073709551615") ) - << Q_UINT64_C(18446744073709551615) - << true; - QTest::newRow( "longlong" ) << QVariant( intMax1 ) << (qulonglong)intMax1 << true; - QTest::newRow( "ulonglong" ) << QVariant( uintMax1 ) << uintMax1 << true; - QTest::newRow( "QChar" ) << QVariant(QChar('a')) << qulonglong('a') << true; - QByteArray bytearray(4, ' '); - bytearray[0] = '3'; - bytearray[1] = '2'; - bytearray[2] = '0'; - bytearray[3] = '1'; - QTest::newRow( "QByteArray" ) << QVariant( bytearray ) << (qulonglong) 3201 << true; - QTest::newRow("int-QJsonValue") << QVariant(QJsonValue(321)) << (qulonglong)321 << true; - QTest::newRow("bool-QJsonValue") << QVariant(QJsonValue(true)) << (qulonglong)0 << false; - - quint64 value64 = (Q_INT64_C(12) << 35) + 8; - QTest::newRow("qint64") << QVariant::fromValue(value64) << qulonglong(value64) << true; - QTest::newRow("long") << QVariant::fromValue(long(464646)) << qulonglong(464646) << true; - QTest::newRow("LONG_MAX") << QVariant::fromValue( LONG_MAX ) << qulonglong(LONG_MAX) << true; - QTest::newRow("ULONG_MAX") << QVariant::fromValue( ULONG_MAX ) << qulonglong(ULONG_MAX) << true; - QTest::newRow( "short" ) << QVariant(short(12)) << qulonglong(12) << true; - QTest::newRow( "-short" ) << QVariant(short(-24)) << qulonglong(-24) << true; - QTest::newRow( "ushort" ) << QVariant(ushort(15)) << qulonglong(15) << true; + addNumberConversions(); } void tst_QVariant::toULongLong() { - QFETCH( QVariant, value ); - QFETCH( qulonglong, result ); - QFETCH( bool, valueOK ); - QVERIFY( value.isValid() ); - EXEC_DEPRECATED_CALL(QVERIFY( value.canConvert( QVariant::ULongLong ) );) - QVERIFY( value.canConvert(QMetaType::fromType()) ); - bool ok; - qulonglong ll = value.toULongLong( &ok ); - QCOMPARE( ll, result ); - QVERIFY( ok == valueOK ); + checkNumberConversions(&QVariant::toULongLong); } void tst_QVariant::toByteArray_data()