From f29896840ce9e93fde9e7c61b922ef71fa0c5590 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 28 Aug 2012 18:00:24 +0200 Subject: [PATCH] Handle invalid dates properly for QDataStream versions < 5. In Qt 5, when streaming an invalid QDate using a QDataStream version earlier than Qt_5_0, QDate.jd is written and read as 0, which is an invalid julian day for Qt versions earlier than 5.0. For Qt 5.0 however, 0 is a valid julian day, so when comparing a deserialised invalid date (read using a QDataStream version < Qt_5_0) against a default-constructed invalid date, they won't compare equal when they should. Task-number: QTBUG-26989 Change-Id: Ia76df493471f3b068c7d7187be20e3178eff2cc7 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 3 +- tests/auto/corelib/tools/qdate/tst_qdate.cpp | 61 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 62582d9..905055c 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -3624,7 +3624,8 @@ QDataStream &operator>>(QDataStream &in, QDate &date) if (in.version() < QDataStream::Qt_5_0) { quint32 jd; in >> jd; - date.jd = jd; + // Older versions consider 0 an invalid jd. + date.jd = (jd != 0 ? jd : QDate::nullJd()); } else { qint64 jd; in >> jd; diff --git a/tests/auto/corelib/tools/qdate/tst_qdate.cpp b/tests/auto/corelib/tools/qdate/tst_qdate.cpp index e97025c..2ce6ab2 100644 --- a/tests/auto/corelib/tools/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/tools/qdate/tst_qdate.cpp @@ -79,6 +79,8 @@ private slots: void operator_gt(); void operator_lt_eq(); void operator_gt_eq(); + void operator_insert_extract_data(); + void operator_insert_extract(); void fromStringDateFormat_data(); void fromStringDateFormat(); void fromStringFormat_data(); @@ -840,6 +842,65 @@ void tst_QDate::operator_gt_eq() QVERIFY( d1 >= d2 ); } +Q_DECLARE_METATYPE(QDataStream::Version) + +void tst_QDate::operator_insert_extract_data() +{ + QTest::addColumn("date"); + QTest::addColumn("dataStreamVersion"); + + QMap versionsToTest; + versionsToTest.insert(QDataStream::Qt_1_0, QString::fromLatin1("Qt_1_0")); + versionsToTest.insert(QDataStream::Qt_2_0, QString::fromLatin1("Qt_2_0")); + versionsToTest.insert(QDataStream::Qt_2_1, QString::fromLatin1("Qt_2_1")); + versionsToTest.insert(QDataStream::Qt_3_0, QString::fromLatin1("Qt_3_0")); + versionsToTest.insert(QDataStream::Qt_3_1, QString::fromLatin1("Qt_3_1")); + versionsToTest.insert(QDataStream::Qt_3_3, QString::fromLatin1("Qt_3_3")); + versionsToTest.insert(QDataStream::Qt_4_0, QString::fromLatin1("Qt_4_0")); + versionsToTest.insert(QDataStream::Qt_4_1, QString::fromLatin1("Qt_4_1")); + versionsToTest.insert(QDataStream::Qt_4_2, QString::fromLatin1("Qt_4_2")); + versionsToTest.insert(QDataStream::Qt_4_3, QString::fromLatin1("Qt_4_3")); + versionsToTest.insert(QDataStream::Qt_4_4, QString::fromLatin1("Qt_4_4")); + versionsToTest.insert(QDataStream::Qt_4_5, QString::fromLatin1("Qt_4_5")); + versionsToTest.insert(QDataStream::Qt_4_6, QString::fromLatin1("Qt_4_6")); + versionsToTest.insert(QDataStream::Qt_4_7, QString::fromLatin1("Qt_4_7")); + versionsToTest.insert(QDataStream::Qt_4_8, QString::fromLatin1("Qt_4_8")); + versionsToTest.insert(QDataStream::Qt_4_9, QString::fromLatin1("Qt_4_9")); + versionsToTest.insert(QDataStream::Qt_5_0, QString::fromLatin1("Qt_5_0")); + + for (QMap::ConstIterator it = versionsToTest.constBegin(); + it != versionsToTest.constEnd(); ++it) { + const QString &version(it.value()); + QTest::newRow(("(invalid) " + version).toLocal8Bit().constData()) << invalidDate() << it.key(); + QTest::newRow(("(1, 1, 1) " + version).toLocal8Bit().constData()) << QDate(1, 1, 1) << it.key(); + QTest::newRow(("(-1, 1, 1) " + version).toLocal8Bit().constData()) << QDate(-1, 1, 1) << it.key(); + QTest::newRow(("(1995, 5, 20) " + version).toLocal8Bit().constData()) << QDate(1995, 5, 20) << it.key(); + + // Test minimums for quint32/qint64. + if (it.key() >= QDataStream::Qt_5_0) + QTest::newRow(("(-4714, 11, 24) " + version).toLocal8Bit().constData()) << QDate(-4714, 11, 24) << it.key(); + else + QTest::newRow(("(-4713, 1, 2) " + version).toLocal8Bit().constData()) << QDate(-4713, 1, 2) << it.key(); + } +} + +void tst_QDate::operator_insert_extract() +{ + QFETCH(QDate, date); + QFETCH(QDataStream::Version, dataStreamVersion); + + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::ReadWrite); + dataStream.setVersion(dataStreamVersion); + dataStream << date; + dataStream.device()->reset(); + QDate deserialised; + dataStream >> deserialised; + QCOMPARE(dataStream.status(), QDataStream::Ok); + + QCOMPARE(deserialised, date); +} + void tst_QDate::fromStringDateFormat_data() { // Since we can't define an element of Qt::DateFormat, d1 will be the date -- 2.7.4