diff options
Diffstat (limited to 'tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp')
-rw-r--r-- | tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp | 199 |
1 files changed, 169 insertions, 30 deletions
diff --git a/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp b/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp index c6490c6158..bfc811eebe 100644 --- a/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp +++ b/tests/auto/corelib/time/qdatetimeparser/tst_qdatetimeparser.cpp @@ -1,42 +1,179 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include <private/qdatetimeparser_p.h> +using namespace Qt::StringLiterals; + +QT_BEGIN_NAMESPACE + +// access to needed members in QDateTimeParser +class QDTPUnitTestParser : public QDateTimeParser +{ +public: + QDTPUnitTestParser() : QDateTimeParser(QMetaType::QDateTime, QDateTimeParser::DateTimeEdit) { } + + // forward data structures + using QDateTimeParser::ParsedSection; + using QDateTimeParser::State; + + // function to manipulate private internals + void setText(QString text) { m_text = text; } + + // forwarding of methods + using QDateTimeParser::parseSection; +}; + +bool operator==(const QDTPUnitTestParser::ParsedSection &a, + const QDTPUnitTestParser::ParsedSection &b) +{ + return a.value == b.value && a.used == b.used && a.zeroes == b.zeroes && a.state == b.state; +} + +// pretty printing for ParsedSection +char *toString(const QDTPUnitTestParser::ParsedSection §ion) +{ + using QTest::toString; + return toString(QByteArray("ParsedSection(") + "state=" + QByteArray::number(section.state) + + ", value=" + QByteArray::number(section.value) + + ", used=" + QByteArray::number(section.used) + + ", zeros=" + QByteArray::number(section.zeroes) + ")"); +} + +QT_END_NAMESPACE + class tst_QDateTimeParser : public QObject { Q_OBJECT + private Q_SLOTS: + void reparse(); + void parseSection_data(); + void parseSection(); + void intermediateYear_data(); void intermediateYear(); }; +void tst_QDateTimeParser::reparse() +{ + const QDateTime when = QDate(2023, 6, 15).startOfDay(); + // QTBUG-114575: 6.2 through 6.5 got back a bogus Qt::TimeZone (with zero offset): + const auto expect = ([](QStringView name) { + // When local time is UTC or a fixed offset from it, the parser prefers + // to interpret a UTC or offset suffix as such, rather than as local + // time (thereby avoiding DST-ness checks). We have to match that here. + if (name == "UTC"_L1) + return Qt::UTC; + if (name.startsWith(u'+') || name.startsWith(u'-')) { + if (std::all_of(name.begin() + 1, name.end(), [](QChar ch) { return ch == u'0'; })) + return Qt::UTC; + if (std::all_of(name.begin() + 1, name.end(), [](QChar ch) { return ch.isDigit(); })) + return Qt::OffsetFromUTC; + // Potential hh:mm offset ? Not yet seen as local tzname[] entry. + } + return Qt::LocalTime; + }); + + const QStringView format = u"dd/MM/yyyy HH:mm t"; + QDateTimeParser who(QMetaType::QDateTime, QDateTimeParser::DateTimeEdit); + QVERIFY(who.parseFormat(format)); + { + // QDTP defaults to the system locale. + const auto state = who.parse(QLocale::system().toString(when, format), -1, when, false); + QCOMPARE(state.state, QDateTimeParser::Acceptable); + QVERIFY(!state.conflicts); + QCOMPARE(state.padded, 0); + QCOMPARE(state.value.timeSpec(), expect(when.timeZoneAbbreviation())); + QCOMPARE(state.value, when); + } + { + // QDT::toString() uses the C locale: + who.setDefaultLocale(QLocale::c()); + const QString zoneName = ([when]() { +#if QT_CONFIG(timezone) + if (QLocale::c() != QLocale::system()) { + const QString local = when.timeRepresentation().displayName( + when, QTimeZone::ShortName, QLocale::c()); + if (!local.isEmpty()) + return local; + } +#endif + return when.timeZoneAbbreviation(); + })(); + const auto state = who.parse(when.toString(format), -1, when, false); + QCOMPARE(state.state, QDateTimeParser::Acceptable); + QVERIFY(!state.conflicts); + QCOMPARE(state.padded, 0); + QCOMPARE(state.value.timeSpec(), expect(zoneName)); + QCOMPARE(state.value, when); + } +} + +void tst_QDateTimeParser::parseSection_data() +{ + QTest::addColumn<QString>("format"); + QTest::addColumn<QString>("input"); + QTest::addColumn<int>("sectionIndex"); + QTest::addColumn<int>("offset"); + QTest::addColumn<QDTPUnitTestParser::ParsedSection>("expected"); + + using ParsedSection = QDTPUnitTestParser::ParsedSection; + using State = QDTPUnitTestParser::State; + QTest::newRow("short-year-begin") + << "yyyy_MM_dd" << "200_12_15" << 0 << 0 + << ParsedSection(State::Intermediate ,200, 3, 0); + + QTest::newRow("short-year-middle") + << "MM-yyyy-dd" << "12-200-15" << 1 << 3 + << ParsedSection(State::Intermediate, 200, 3, 0); + + QTest::newRow("negative-year-middle-5") + << "MM-yyyy-dd" << "12--2000-15" << 1 << 3 + << ParsedSection(State::Acceptable, -2000, 5, 0); + + QTest::newRow("short-negative-year-middle-4") + << "MM-yyyy-dd" << "12--200-15" << 1 << 3 + << ParsedSection(State::Intermediate, -200, 4, 0); + + QTest::newRow("short-negative-year-middle-3") + << "MM-yyyy-dd" << "12--20-15" << 1 << 3 + << ParsedSection(State::Intermediate, -20, 3, 0); + + QTest::newRow("short-negative-year-middle-2") + << "MM-yyyy-dd" << "12--2-15" << 1 << 3 + << ParsedSection(State::Intermediate, -2, 2, 0); + + QTest::newRow("short-negative-year-middle-1") + << "MM-yyyy-dd" << "12---15" << 1 << 3 + << ParsedSection(State::Intermediate, 0, 1, 0); + + // Here the -15 will be understood as year, with separator and day omitted, + // although it could equally be read as month and day with missing year. + QTest::newRow("short-negative-year-middle-0") + << "MM-yyyy-dd" << "12--15" << 1 << 3 + << ParsedSection(State::Intermediate, -15, 3, 0); +} + +void tst_QDateTimeParser::parseSection() +{ + QFETCH(QString, format); + QFETCH(QString, input); + QFETCH(int, sectionIndex); + QFETCH(int, offset); + QFETCH(QDTPUnitTestParser::ParsedSection, expected); + + QDTPUnitTestParser testParser; + + QVERIFY(testParser.parseFormat(format)); + QDateTime val(QDate(1900, 1, 1).startOfDay()); + + testParser.setText(input); + auto result = testParser.parseSection(val, sectionIndex, offset); + QCOMPARE(result, expected); +} + void tst_QDateTimeParser::intermediateYear_data() { QTest::addColumn<QString>("format"); @@ -61,10 +198,12 @@ void tst_QDateTimeParser::intermediateYear() QVERIFY(testParser.parseFormat(format)); + // Indian/Cocos has a transition at the start of 1900, so it started this + // day at 00:02:20, throwing a time offset into QDTP. QDateTime val(QDate(1900, 1, 1).startOfDay()); const QDateTimeParser::StateNode tmp = testParser.parse(input, -1, val, false); QCOMPARE(tmp.state, QDateTimeParser::Intermediate); - QCOMPARE(tmp.value, expected.startOfDay()); + QCOMPARE(tmp.value.date(), expected); } QTEST_APPLESS_MAIN(tst_QDateTimeParser) |