TestLib: provide helper functions to test relational operators
The patch provides two sets of functions: * functions to perform compile-time check for all cv-ref combinations * functions that actually verify the comparison results for all cv-ref combinations. For now it does not test operator<=>(), even if compiled with C++20, because Qt types do not yet implement it. The patch uses the new helper functions to improve testing of date and time classes, because they already provide a full set of relational operators. Change-Id: I8bd869c489543719ea856d6609cac53cbd4dc122 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
e4bde15e14
commit
bfb237d19a
@ -21,6 +21,7 @@ qt_internal_add_module(Test
|
||||
qbenchmarkmetric.cpp qbenchmarkmetric.h qbenchmarkmetric_p.h
|
||||
qbenchmarkperfevents.cpp qbenchmarkperfevents_p.h
|
||||
qbenchmarktimemeasurers_p.h
|
||||
qcomparisontesthelper.cpp qcomparisontesthelper_p.h
|
||||
qcsvbenchmarklogger.cpp qcsvbenchmarklogger_p.h
|
||||
qemulationdetector_p.h
|
||||
qjunittestlogger.cpp qjunittestlogger_p.h
|
||||
|
22
src/testlib/qcomparisontesthelper.cpp
Normal file
22
src/testlib/qcomparisontesthelper.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qcomparisontesthelper_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QTestPrivate {
|
||||
|
||||
QByteArray formatTypeWithCRefImpl(QMetaType type, bool isConst, bool isRef, bool isRvalueRef)
|
||||
{
|
||||
QByteArray res(type.name());
|
||||
if (isConst)
|
||||
res.append(" const");
|
||||
if (isRef)
|
||||
res.append(isRvalueRef ? " &&" : " &");
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace QTestPrivate
|
||||
|
||||
QT_END_NAMESPACE
|
239
src/testlib/qcomparisontesthelper_p.h
Normal file
239
src/testlib/qcomparisontesthelper_p.h
Normal file
@ -0,0 +1,239 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QCOMPARISONTESTHELPER_P_H
|
||||
#define QCOMPARISONTESTHELPER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/q20type_traits.h>
|
||||
#include <QtTest/qtest.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QTestPrivate {
|
||||
|
||||
Q_TESTLIB_EXPORT QByteArray formatTypeWithCRefImpl(QMetaType type, bool isConst,
|
||||
bool isRef, bool isRvalueRef);
|
||||
|
||||
template <typename T>
|
||||
QByteArray formatTypeWithCRef()
|
||||
{
|
||||
return formatTypeWithCRefImpl(QMetaType::fromType<q20::remove_cvref_t<T>>(),
|
||||
std::is_const_v<std::remove_reference_t<T>>,
|
||||
std::is_reference_v<T>,
|
||||
std::is_rvalue_reference_v<T>);
|
||||
}
|
||||
|
||||
#define FOR_EACH_CREF(Func, Left, Right, Op, Result) \
|
||||
Func(Left &, Right &, Op, Result) \
|
||||
Func(Left &, Right const &, Op, Result) \
|
||||
Func(Left &, Right &&, Op, Result) \
|
||||
Func(Left &, Right const &&, Op, Result) \
|
||||
Func(Left const &, Right &, Op, Result) \
|
||||
Func(Left const &, Right const &, Op, Result) \
|
||||
Func(Left const &, Right &&, Op, Result) \
|
||||
Func(Left const &, Right const &&, Op, Result) \
|
||||
Func(Left &&, Right &, Op, Result) \
|
||||
Func(Left &&, Right const &, Op, Result) \
|
||||
Func(Left &&, Right &&, Op, Result) \
|
||||
Func(Left &&, Right const &&, Op, Result) \
|
||||
Func(Left const &&, Right &, Op, Result) \
|
||||
Func(Left const &&, Right const &, Op, Result) \
|
||||
Func(Left const &&, Right &&, Op, Result) \
|
||||
Func(Left const &&, Right const &&, Op, Result) \
|
||||
/* END */
|
||||
|
||||
#define CHECK_SINGLE_OPERATOR(Left, Right, Op, Result) \
|
||||
do { \
|
||||
constexpr bool qtest_op_check_isImplNoexcept \
|
||||
= noexcept(std::declval<Left>() Op std::declval<Right>()); \
|
||||
if constexpr (!qtest_op_check_isImplNoexcept) { \
|
||||
QEXPECT_FAIL("", QByteArray("(" + formatTypeWithCRef<Left>() \
|
||||
+ " " #Op " " + formatTypeWithCRef<Right>() \
|
||||
+ ") is not noexcept").constData(), \
|
||||
Continue); \
|
||||
/* Ideally, operators should be noexcept, so warn if they are not. */ \
|
||||
/* Do not make it a hard error, because the fix is not always trivial. */ \
|
||||
QVERIFY(qtest_op_check_isImplNoexcept); \
|
||||
} \
|
||||
static_assert(std::is_convertible_v<decltype( \
|
||||
std::declval<Left>() Op std::declval<Right>()), Result>); \
|
||||
if constexpr (!std::is_same_v<Left, Right>) { \
|
||||
static_assert(std::is_convertible_v<decltype( \
|
||||
std::declval<Right>() Op std::declval<Left>()), Result>); \
|
||||
} \
|
||||
} while (false); \
|
||||
/* END */
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
This function checks that the types \c LeftType and \c RightType properly
|
||||
define {in}equality operators (== and !=). The checks are performed for
|
||||
all combinations of cvref-qualified lvalues and rvalues.
|
||||
*/
|
||||
template <typename LeftType, typename RightType = LeftType>
|
||||
void testEqualityOperatorsCompile()
|
||||
{
|
||||
FOR_EACH_CREF(CHECK_SINGLE_OPERATOR, LeftType, RightType, ==, bool)
|
||||
FOR_EACH_CREF(CHECK_SINGLE_OPERATOR, LeftType, RightType, !=, bool)
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
This function checks that the types \c LeftType and \c RightType properly
|
||||
define all comparison operators (==, !=, <, >, <=, >=). The checks are
|
||||
performed for all combinations of cvref-qualified lvalues and rvalues.
|
||||
*/
|
||||
template <typename LeftType, typename RightType = LeftType>
|
||||
void testAllComparisonOperatorsCompile()
|
||||
{
|
||||
testEqualityOperatorsCompile<LeftType, RightType>();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
FOR_EACH_CREF(CHECK_SINGLE_OPERATOR, LeftType, RightType, >, bool)
|
||||
FOR_EACH_CREF(CHECK_SINGLE_OPERATOR, LeftType, RightType, <, bool)
|
||||
FOR_EACH_CREF(CHECK_SINGLE_OPERATOR, LeftType, RightType, >=, bool)
|
||||
FOR_EACH_CREF(CHECK_SINGLE_OPERATOR, LeftType, RightType, <=, bool)
|
||||
}
|
||||
|
||||
#undef CHECK_SINGLE_OPERATOR
|
||||
#undef FOR_EACH_CREF
|
||||
|
||||
#define CHECK_RUNTIME_LR(Left, Right, Op, Expected) \
|
||||
do { \
|
||||
QCOMPARE_EQ(Left Op Right, Expected); \
|
||||
QCOMPARE_EQ(std::move(Left) Op Right, Expected); \
|
||||
QCOMPARE_EQ(Left Op std::move(Right), Expected); \
|
||||
QCOMPARE_EQ(std::move(Left) Op std::move(Right), Expected); \
|
||||
} while (false); \
|
||||
/* END */
|
||||
|
||||
#define CHECK_RUNTIME_CREF(Func, Left, Right, Op, Expected) \
|
||||
Func(Left, Right, Op, Expected); \
|
||||
Func(std::as_const(Left), Right, Op, Expected); \
|
||||
Func(Left, std::as_const(Right), Op, Expected); \
|
||||
Func(std::as_const(Left), std::as_const(Right), Op, Expected); \
|
||||
/* END */
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Basic testing of equality operators.
|
||||
|
||||
The helper function tests {in}equality operators (== and !=) for the \a lhs
|
||||
operand of type \c {LeftType} and the \a rhs operand of type \c {RightType}.
|
||||
|
||||
The \a expectedEqual parameter is an expected result for \c {operator==()}.
|
||||
|
||||
\note Any test calling this method will need to check the test state after
|
||||
doing so, if there is any later code in the test.
|
||||
|
||||
\code
|
||||
QTime early(12, 34, 56, 00);
|
||||
QTime later(12, 34, 56, 01);
|
||||
QTestPrivate::testEqualityOperators(early, later, false);
|
||||
if (QTest:currentTestFailed())
|
||||
return;
|
||||
\endcode
|
||||
*/
|
||||
template <typename LeftType, typename RightType>
|
||||
void testEqualityOperators(LeftType lhs, RightType rhs, bool expectedEqual)
|
||||
{
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, ==, expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, !=, !expectedEqual)
|
||||
if constexpr (!std::is_same_v<LeftType, RightType>) {
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, ==, expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, !=, !expectedEqual)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Basic testing of equality and relation operators.
|
||||
|
||||
The helper function tests all six relation and equality operators
|
||||
(==, !=, <, >, <=, >=) for the \a lhs operand of type \c {LeftType} and
|
||||
the \a rhs operand of type \c {RightType}.
|
||||
|
||||
The \c OrderingType must be one of QPartialOrdering, QStrongOrdering, or
|
||||
QWeakOrdering.
|
||||
|
||||
The \a expectedOrdering parameter provides the expected
|
||||
relation between \a lhs and \a rhs.
|
||||
|
||||
\note Any test calling this method will need to check the test state after
|
||||
doing so, if there is any later code in the test.
|
||||
|
||||
\code
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QDateTime later = now.addMSec(1);
|
||||
QTestPrivate::testComparisonOperators(now, later, QWeakOrdering::Less);
|
||||
if (QTest:currentTestFailed())
|
||||
return;
|
||||
\endcode
|
||||
*/
|
||||
template <typename LeftType, typename RightType, typename OrderingType>
|
||||
void testAllComparisonOperators(LeftType lhs, RightType rhs, OrderingType expectedOrdering)
|
||||
{
|
||||
constexpr bool isQOrderingType = std::is_same_v<OrderingType, QPartialOrdering>
|
||||
|| std::is_same_v<OrderingType, QWeakOrdering>
|
||||
|| std::is_same_v<OrderingType, QStrongOrdering>;
|
||||
|
||||
static_assert(isQOrderingType,
|
||||
"Please provide, as the expectedOrdering parameter, a value "
|
||||
"of one of the Q{Partial,Weak,Strong}Ordering types.");
|
||||
|
||||
// We have all sorts of operator==() between Q*Ordering and std::*_ordering
|
||||
// types, so we can just compare to QPartialOrdering.
|
||||
const bool expectedEqual = expectedOrdering == QPartialOrdering::Equivalent;
|
||||
const bool expectedLess = expectedOrdering == QPartialOrdering::Less;
|
||||
const bool expectedUnordered = expectedOrdering == QPartialOrdering::Unordered;
|
||||
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, ==,
|
||||
!expectedUnordered && expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, !=,
|
||||
expectedUnordered || !expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, <,
|
||||
!expectedUnordered && expectedLess)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, >,
|
||||
!expectedUnordered && !expectedLess && !expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, <=,
|
||||
!expectedUnordered && (expectedEqual || expectedLess))
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, lhs, rhs, >=,
|
||||
!expectedUnordered && !expectedLess)
|
||||
|
||||
if constexpr (!std::is_same_v<LeftType, RightType>) {
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, ==,
|
||||
!expectedUnordered && expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, !=,
|
||||
expectedUnordered || !expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, <,
|
||||
!expectedUnordered && !expectedLess && !expectedEqual)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, >,
|
||||
!expectedUnordered && expectedLess)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, <=,
|
||||
!expectedUnordered && !expectedLess)
|
||||
CHECK_RUNTIME_CREF(CHECK_RUNTIME_LR, rhs, lhs, >=,
|
||||
!expectedUnordered && (expectedEqual || expectedLess))
|
||||
}
|
||||
}
|
||||
|
||||
#undef CHECK_RUNTIME_CREF
|
||||
#undef CHECK_RUNTIME_LR
|
||||
|
||||
} // namespace QTestPrivate
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCOMPARISONTESTHELPER_P_H
|
@ -19,4 +19,5 @@ qt_internal_add_test(tst_qdate
|
||||
QT_NO_KEYWORDS
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::TestPrivate
|
||||
)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <QTimeZone>
|
||||
|
||||
#include <private/qglobal_p.h> // for the icu feature test
|
||||
#include <private/qcomparisontesthelper_p.h>
|
||||
#include <private/qdatetime_p.h>
|
||||
#if !QT_CONFIG(timezone)
|
||||
# include <private/qtenvironmentvariables_p.h> // for qTzName()
|
||||
@ -57,12 +58,12 @@ private Q_SLOTS:
|
||||
void addYears_data();
|
||||
void addYears();
|
||||
void daysTo();
|
||||
void orderingCompiles();
|
||||
void operator_eq_eq_data();
|
||||
void operator_eq_eq();
|
||||
void operator_lt();
|
||||
void operator_gt();
|
||||
void operator_lt_eq();
|
||||
void operator_gt_eq();
|
||||
void ordering_data();
|
||||
void ordering();
|
||||
void ordering_chrono_types();
|
||||
void operator_insert_extract_data();
|
||||
void operator_insert_extract();
|
||||
#if QT_CONFIG(datestring)
|
||||
@ -992,6 +993,17 @@ void tst_QDate::daysTo()
|
||||
QCOMPARE(zeroDate.daysTo(minDate), minJd);
|
||||
}
|
||||
|
||||
void tst_QDate::orderingCompiles()
|
||||
{
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QDate>();
|
||||
#if __cpp_lib_chrono >= 201907L
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QDate, std::chrono::year_month_day>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QDate, std::chrono::year_month_day_last>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QDate, std::chrono::year_month_weekday>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QDate, std::chrono::year_month_weekday_last>();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QDate::operator_eq_eq_data()
|
||||
{
|
||||
QTest::addColumn<QDate>("d1");
|
||||
@ -1028,137 +1040,91 @@ void tst_QDate::operator_eq_eq()
|
||||
QFETCH(QDate, d2);
|
||||
QFETCH(bool, expectEqual);
|
||||
|
||||
bool equal = d1 == d2;
|
||||
QCOMPARE(equal, expectEqual);
|
||||
bool notEqual = d1 != d2;
|
||||
QCOMPARE(notEqual, !expectEqual);
|
||||
QTestPrivate::testEqualityOperators(d1, d2, expectEqual);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
if (equal)
|
||||
if (expectEqual)
|
||||
QVERIFY(qHash(d1) == qHash(d2));
|
||||
}
|
||||
|
||||
void tst_QDate::operator_lt()
|
||||
void tst_QDate::ordering_data()
|
||||
{
|
||||
QDate d1(2000,1,2);
|
||||
QDate d2(2000,1,2);
|
||||
QVERIFY( !(d1 < d2) );
|
||||
QTest::addColumn<QDate>("left");
|
||||
QTest::addColumn<QDate>("right");
|
||||
QTest::addColumn<QStrongOrdering>("expectedOrdering");
|
||||
|
||||
d1 = QDate(2001,12,4);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 < d2 );
|
||||
|
||||
d1 = QDate(2001,11,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 < d2 );
|
||||
|
||||
d1 = QDate(2000,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 < d2 );
|
||||
|
||||
d1 = QDate(2002,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 < d2) );
|
||||
|
||||
d1 = QDate(2001,12,5);
|
||||
d2 = QDate(2001,11,5);
|
||||
QVERIFY( !(d1 < d2) );
|
||||
|
||||
d1 = QDate(2001,12,6);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 < d2) );
|
||||
QTest::newRow("2000-1-2_vs_2000-1-2")
|
||||
<< QDate(2000, 1, 2) << QDate(2000, 1, 2) << QStrongOrdering::Equivalent;
|
||||
QTest::newRow("2001-12-4_vs_2001-12-5")
|
||||
<< QDate(2001, 12, 4) << QDate(2001, 12, 5) << QStrongOrdering::Less;
|
||||
QTest::newRow("2001-11-5_vs_2001-12-5")
|
||||
<< QDate(2001, 11, 5) << QDate(2001, 12, 5) << QStrongOrdering::Less;
|
||||
QTest::newRow("2000-12-5_vs_2001-12-5")
|
||||
<< QDate(2000, 12, 5) << QDate(2001, 12, 5) << QStrongOrdering::Less;
|
||||
QTest::newRow("2002-12-5_vs_2001-12-5")
|
||||
<< QDate(2002, 12, 5) << QDate(2001, 12, 5) << QStrongOrdering::Greater;
|
||||
QTest::newRow("2001-12-5_vs_2001-11-5")
|
||||
<< QDate(2001, 12, 5) << QDate(2001, 11, 5) << QStrongOrdering::Greater;
|
||||
QTest::newRow("2001-12-6_vs_2001-12-5")
|
||||
<< QDate(2001, 12, 6) << QDate(2001, 12, 5) << QStrongOrdering::Greater;
|
||||
}
|
||||
|
||||
void tst_QDate::operator_gt()
|
||||
void tst_QDate::ordering()
|
||||
{
|
||||
QDate d1(2000,1,2);
|
||||
QDate d2(2000,1,2);
|
||||
QVERIFY( !(d1 > d2) );
|
||||
QFETCH(QDate, left);
|
||||
QFETCH(QDate, right);
|
||||
QFETCH(QStrongOrdering, expectedOrdering);
|
||||
|
||||
d1 = QDate(2001,12,4);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 > d2) );
|
||||
|
||||
d1 = QDate(2001,11,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 > d2) );
|
||||
|
||||
d1 = QDate(2000,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 > d2) );
|
||||
|
||||
d1 = QDate(2002,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 > d2 );
|
||||
|
||||
d1 = QDate(2001,12,5);
|
||||
d2 = QDate(2001,11,5);
|
||||
QVERIFY( d1 > d2 );
|
||||
|
||||
d1 = QDate(2001,12,6);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 > d2 );
|
||||
QTestPrivate::testAllComparisonOperators(left, right, expectedOrdering);
|
||||
}
|
||||
|
||||
void tst_QDate::operator_lt_eq()
|
||||
void tst_QDate::ordering_chrono_types()
|
||||
{
|
||||
QDate d1(2000,1,2);
|
||||
QDate d2(2000,1,2);
|
||||
QVERIFY( d1 <= d2 );
|
||||
#if __cpp_lib_chrono >= 201907L
|
||||
using namespace std::chrono;
|
||||
QDate friday(2001, 11, 30); // the 5th Friday of November 2001
|
||||
// std::chrono::year_month_day
|
||||
QTestPrivate::testAllComparisonOperators(friday, year_month_day(2001y, November, 29d),
|
||||
QStrongOrdering::Greater);
|
||||
QTestPrivate::testAllComparisonOperators(friday, year_month_day(2001y, November, 30d),
|
||||
QStrongOrdering::Equivalent);
|
||||
QTestPrivate::testAllComparisonOperators(friday, year_month_day(2001y, December, 1d),
|
||||
QStrongOrdering::Less);
|
||||
|
||||
d1 = QDate(2001,12,4);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 <= d2 );
|
||||
// std::chrono::year_month_day_last
|
||||
QTestPrivate::testAllComparisonOperators(friday, year_month_day_last(2001y, {October / last}),
|
||||
QStrongOrdering::Greater);
|
||||
QTestPrivate::testAllComparisonOperators(friday, year_month_day_last(2001y, {November / last}),
|
||||
QStrongOrdering::Equivalent);
|
||||
QTestPrivate::testAllComparisonOperators(friday, year_month_day_last(2001y, {December / last}),
|
||||
QStrongOrdering::Less);
|
||||
|
||||
d1 = QDate(2001,11,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 <= d2 );
|
||||
// std::chrono::year_month_weekday
|
||||
QTestPrivate::testAllComparisonOperators(friday,
|
||||
year_month_weekday(2001y, November, Thursday[5]),
|
||||
QStrongOrdering::Greater);
|
||||
QTestPrivate::testAllComparisonOperators(friday,
|
||||
year_month_weekday(2001y, November, Friday[5]),
|
||||
QStrongOrdering::Equivalent);
|
||||
QTestPrivate::testAllComparisonOperators(friday,
|
||||
year_month_weekday(2001y, December, Saturday[1]),
|
||||
QStrongOrdering::Less);
|
||||
|
||||
d1 = QDate(2000,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 <= d2 );
|
||||
|
||||
d1 = QDate(2002,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 <= d2) );
|
||||
|
||||
d1 = QDate(2001,12,5);
|
||||
d2 = QDate(2001,11,5);
|
||||
QVERIFY( !(d1 <= d2) );
|
||||
|
||||
d1 = QDate(2001,12,6);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 <= d2) );
|
||||
}
|
||||
|
||||
void tst_QDate::operator_gt_eq()
|
||||
{
|
||||
QDate d1(2000,1,2);
|
||||
QDate d2(2000,1,2);
|
||||
QVERIFY( d1 >= d2 );
|
||||
|
||||
d1 = QDate(2001,12,4);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 >= d2) );
|
||||
|
||||
d1 = QDate(2001,11,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 >= d2) );
|
||||
|
||||
d1 = QDate(2000,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( !(d1 >= d2) );
|
||||
|
||||
d1 = QDate(2002,12,5);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 >= d2 );
|
||||
|
||||
d1 = QDate(2001,12,5);
|
||||
d2 = QDate(2001,11,5);
|
||||
QVERIFY( d1 >= d2 );
|
||||
|
||||
d1 = QDate(2001,12,6);
|
||||
d2 = QDate(2001,12,5);
|
||||
QVERIFY( d1 >= d2 );
|
||||
// std::chrono::year_month_weekday_last
|
||||
QDate thursday(2001, 11, 29); // the last Thursday of November 2001
|
||||
QTestPrivate::testAllComparisonOperators(thursday, year_month_weekday_last(2001y, November,
|
||||
Wednesday[last]),
|
||||
QStrongOrdering::Greater);
|
||||
QTestPrivate::testAllComparisonOperators(thursday, year_month_weekday_last(2001y, November,
|
||||
Thursday[last]),
|
||||
QStrongOrdering::Equivalent);
|
||||
QTestPrivate::testAllComparisonOperators(thursday, year_month_weekday_last(2001y, November,
|
||||
Friday[last]),
|
||||
QStrongOrdering::Less);
|
||||
#else
|
||||
QSKIP("This test requires C++20-level <chrono> support enabled in the standard library.");
|
||||
#endif // __cpp_lib_chrono >= 201907L
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QDataStream::Version)
|
||||
|
@ -19,6 +19,7 @@ qt_internal_add_test(tst_qdatetime
|
||||
QT_NO_KEYWORDS
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::TestPrivate
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <QTimeZone>
|
||||
#include <private/qdatetime_p.h>
|
||||
#include <private/qtenvironmentvariables_p.h> // for qTzSet(), qTzName()
|
||||
#include <private/qcomparisontesthelper_p.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <qt_windows.h>
|
||||
@ -99,8 +100,11 @@ private Q_SLOTS:
|
||||
void secsTo();
|
||||
void msecsTo_data() { addMSecs_data(); }
|
||||
void msecsTo();
|
||||
void orderingCompiles();
|
||||
void operator_eqeq_data();
|
||||
void operator_eqeq();
|
||||
void ordering_data();
|
||||
void ordering();
|
||||
void operator_insert_extract_data();
|
||||
void operator_insert_extract();
|
||||
void currentDateTime();
|
||||
@ -1985,6 +1989,11 @@ void tst_QDateTime::msecsTo()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QDateTime::orderingCompiles()
|
||||
{
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QDateTime>();
|
||||
}
|
||||
|
||||
void tst_QDateTime::currentDateTime()
|
||||
{
|
||||
time_t buf1, buf2;
|
||||
@ -2463,23 +2472,24 @@ void tst_QDateTime::operator_eqeq()
|
||||
QFETCH(bool, expectEqual);
|
||||
QFETCH(bool, checkEuro);
|
||||
|
||||
QVERIFY(dt1 == dt1);
|
||||
QVERIFY(!(dt1 != dt1));
|
||||
QTestPrivate::testEqualityOperators(dt1, dt1, true);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
QVERIFY(dt2 == dt2);
|
||||
QVERIFY(!(dt2 != dt2));
|
||||
QTestPrivate::testEqualityOperators(dt2, dt2, true);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
QTestPrivate::testEqualityOperators(dt1, dt2, expectEqual);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
QVERIFY(dt1 != QDateTime::currentDateTime());
|
||||
QVERIFY(dt2 != QDateTime::currentDateTime());
|
||||
|
||||
QVERIFY(dt1.toUTC() == dt1.toUTC());
|
||||
|
||||
bool equal = dt1 == dt2;
|
||||
QCOMPARE(equal, expectEqual);
|
||||
bool notEqual = dt1 != dt2;
|
||||
QCOMPARE(notEqual, !expectEqual);
|
||||
|
||||
if (equal)
|
||||
if (expectEqual)
|
||||
QVERIFY(qHash(dt1) == qHash(dt2));
|
||||
|
||||
if (checkEuro && zoneIsCET) {
|
||||
@ -2488,6 +2498,64 @@ void tst_QDateTime::operator_eqeq()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QDateTime::ordering_data()
|
||||
{
|
||||
QTest::addColumn<QDateTime>("left");
|
||||
QTest::addColumn<QDateTime>("right");
|
||||
QTest::addColumn<QWeakOrdering>("expectedOrdering");
|
||||
|
||||
Q_CONSTINIT static const auto constructName = [](const QDateTime &dt) -> QByteArray {
|
||||
if (dt.isNull())
|
||||
return "null";
|
||||
if (!dt.isValid())
|
||||
return "invalid";
|
||||
return dt.toString(Qt::ISODateWithMs).toLatin1();
|
||||
};
|
||||
|
||||
Q_CONSTINIT static const auto generateRow =
|
||||
[](const QDateTime &left, const QDateTime &right, QWeakOrdering ordering) {
|
||||
const QByteArray leftStr = constructName(left);
|
||||
const QByteArray rightStr = constructName(right);
|
||||
QTest::addRow("%s_vs_%s", leftStr.constData(), rightStr.constData())
|
||||
<< left << right << ordering;
|
||||
};
|
||||
|
||||
QDateTime june(QDate(2012, 6, 20), QTime(14, 33, 2, 500));
|
||||
QDateTime juneLater = june.addMSecs(1);
|
||||
QDateTime badDay(QDate(2012, 20, 6), QTime(14, 33, 2, 500)); // Invalid
|
||||
QDateTime epoch(QDate(1970, 1, 1), QTime(0, 0), UTC); // UTC epoch
|
||||
QDateTime nextDay = epoch.addDays(1);
|
||||
QDateTime prevDay = epoch.addDays(-1);
|
||||
// Ensure that different times may be equal when considering timezone.
|
||||
QDateTime epochEast1h(epoch.addSecs(3600));
|
||||
epochEast1h.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(3600));
|
||||
QDateTime epochWest1h(epoch.addSecs(-3600));
|
||||
epochWest1h.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(-3600));
|
||||
QDateTime local1970(epoch.date(), epoch.time()); // Local time's epoch
|
||||
|
||||
generateRow(june, june, QWeakOrdering::Equivalent);
|
||||
generateRow(june, juneLater, QWeakOrdering::Less);
|
||||
generateRow(june, badDay, QWeakOrdering::Greater);
|
||||
generateRow(badDay, QDateTime(), QWeakOrdering::Equivalent);
|
||||
generateRow(june, QDateTime(), QWeakOrdering::Greater);
|
||||
generateRow(epoch, nextDay, QWeakOrdering::Less);
|
||||
generateRow(epoch, prevDay, QWeakOrdering::Greater);
|
||||
generateRow(epoch, epochEast1h, QWeakOrdering::Equivalent);
|
||||
generateRow(epoch, epochWest1h, QWeakOrdering::Equivalent);
|
||||
generateRow(epochEast1h, epochWest1h, QWeakOrdering::Equivalent);
|
||||
if (epochTimeType == LocalTimeIsUtc)
|
||||
generateRow(epoch, local1970, QWeakOrdering::Equivalent);
|
||||
}
|
||||
|
||||
void tst_QDateTime::ordering()
|
||||
{
|
||||
QFETCH(QDateTime, left);
|
||||
QFETCH(QDateTime, right);
|
||||
QFETCH(QWeakOrdering, expectedOrdering);
|
||||
|
||||
QTestPrivate::testAllComparisonOperators(left, right, expectedOrdering);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QDataStream::Version)
|
||||
|
||||
void tst_QDateTime::operator_insert_extract_data()
|
||||
|
@ -19,4 +19,5 @@ qt_internal_add_test(tst_qtime
|
||||
QT_NO_KEYWORDS
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::TestPrivate
|
||||
)
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <private/qglobal_p.h>
|
||||
#include <private/qcomparisontesthelper_p.h>
|
||||
#include <QTest>
|
||||
#include "qdatetime.h"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
@ -27,12 +28,11 @@ private Q_SLOTS:
|
||||
void addMSecs();
|
||||
void addSecs_data();
|
||||
void addSecs();
|
||||
void orderingCompiles();
|
||||
void operator_eq_eq_data();
|
||||
void operator_eq_eq();
|
||||
void operator_lt();
|
||||
void operator_gt();
|
||||
void operator_lt_eq();
|
||||
void operator_gt_eq();
|
||||
void ordering_data();
|
||||
void ordering();
|
||||
#if QT_CONFIG(datestring)
|
||||
# if QT_CONFIG(datetimeparser)
|
||||
void fromStringFormat_data();
|
||||
@ -320,6 +320,11 @@ void tst_QTime::msecsTo()
|
||||
QCOMPARE( t1.msecsTo( t2 ), delta );
|
||||
}
|
||||
|
||||
void tst_QTime::orderingCompiles()
|
||||
{
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<QTime>();
|
||||
}
|
||||
|
||||
void tst_QTime::operator_eq_eq_data()
|
||||
{
|
||||
QTest::addColumn<QTime>("t1");
|
||||
@ -345,169 +350,44 @@ void tst_QTime::operator_eq_eq()
|
||||
QFETCH(QTime, t2);
|
||||
QFETCH(bool, expectEqual);
|
||||
|
||||
bool equal = t1 == t2;
|
||||
QCOMPARE(equal, expectEqual);
|
||||
bool notEqual = t1 != t2;
|
||||
QCOMPARE(notEqual, !expectEqual);
|
||||
QTestPrivate::testEqualityOperators(t1, t2, expectEqual);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
if (equal)
|
||||
if (expectEqual)
|
||||
QVERIFY(qHash(t1) == qHash(t2));
|
||||
}
|
||||
|
||||
void tst_QTime::operator_lt()
|
||||
void tst_QTime::ordering_data()
|
||||
{
|
||||
QTime t1(0,0,0,0);
|
||||
QTime t2(0,0,0,0);
|
||||
QVERIFY( !(t1 < t2) );
|
||||
QTest::addColumn<QTime>("left");
|
||||
QTest::addColumn<QTime>("right");
|
||||
QTest::addColumn<QStrongOrdering>("expectedOrdering");
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(12,34,56,30);
|
||||
QVERIFY( t1 < t2 );
|
||||
auto generateRow = [](QTime t1, QTime t2, QStrongOrdering ordering) {
|
||||
const QByteArray t1Str = t1.toString("hh:mm:ss.zz").toLatin1();
|
||||
const QByteArray t2Str = t2.toString("hh:mm:ss.zz").toLatin1();
|
||||
QTest::addRow("%s_vs_%s", t1Str.constData(), t2Str.constData()) << t1 << t2 << ordering;
|
||||
};
|
||||
|
||||
t1 = QTime(13,34,46,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 < t2 );
|
||||
|
||||
t1 = QTime(13,24,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 < t2 );
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 < t2 );
|
||||
|
||||
t1 = QTime(14,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 < t2) );
|
||||
|
||||
t1 = QTime(13,44,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 < t2) );
|
||||
|
||||
t1 = QTime(13,34,56,20);
|
||||
t2 = QTime(13,34,46,20);
|
||||
QVERIFY( !(t1 < t2) );
|
||||
|
||||
t1 = QTime(13,44,56,30);
|
||||
t2 = QTime(13,44,56,20);
|
||||
QVERIFY( !(t1 < t2) );
|
||||
generateRow(QTime(0, 0), QTime(0, 0), QStrongOrdering::Equivalent);
|
||||
generateRow(QTime(12, 34, 56, 20), QTime(12, 34, 56, 30), QStrongOrdering::Less);
|
||||
generateRow(QTime(13, 34, 46, 20), QTime(13, 34, 56, 20), QStrongOrdering::Less);
|
||||
generateRow(QTime(13, 24, 56, 20), QTime(13, 34, 56, 20), QStrongOrdering::Less);
|
||||
generateRow(QTime(12, 34, 56, 20), QTime(13, 34, 56, 20), QStrongOrdering::Less);
|
||||
generateRow(QTime(14, 34, 56, 20), QTime(13, 34, 56, 20), QStrongOrdering::Greater);
|
||||
generateRow(QTime(13, 44, 56, 20), QTime(13, 34, 56, 20), QStrongOrdering::Greater);
|
||||
generateRow(QTime(13, 34, 56, 20), QTime(13, 34, 46, 20), QStrongOrdering::Greater);
|
||||
generateRow(QTime(13, 34, 56, 30), QTime(13, 34, 56, 20), QStrongOrdering::Greater);
|
||||
}
|
||||
|
||||
void tst_QTime::operator_gt()
|
||||
void tst_QTime::ordering()
|
||||
{
|
||||
QTime t1(0,0,0,0);
|
||||
QTime t2(0,0,0,0);
|
||||
QVERIFY( !(t1 > t2) );
|
||||
QFETCH(QTime, left);
|
||||
QFETCH(QTime, right);
|
||||
QFETCH(QStrongOrdering, expectedOrdering);
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(12,34,56,30);
|
||||
QVERIFY( !(t1 > t2) );
|
||||
|
||||
t1 = QTime(13,34,46,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 > t2) );
|
||||
|
||||
t1 = QTime(13,24,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 > t2) );
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 > t2) );
|
||||
|
||||
t1 = QTime(14,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 > t2 );
|
||||
|
||||
t1 = QTime(13,44,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 > t2 );
|
||||
|
||||
t1 = QTime(13,34,56,20);
|
||||
t2 = QTime(13,34,46,20);
|
||||
QVERIFY( t1 > t2 );
|
||||
|
||||
t1 = QTime(13,44,56,30);
|
||||
t2 = QTime(13,44,56,20);
|
||||
QVERIFY( t1 > t2 );
|
||||
}
|
||||
|
||||
void tst_QTime::operator_lt_eq()
|
||||
{
|
||||
QTime t1(0,0,0,0);
|
||||
QTime t2(0,0,0,0);
|
||||
QVERIFY( t1 <= t2 );
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(12,34,56,30);
|
||||
QVERIFY( t1 <= t2 );
|
||||
|
||||
t1 = QTime(13,34,46,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 <= t2 );
|
||||
|
||||
t1 = QTime(13,24,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 <= t2 );
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 <= t2 );
|
||||
|
||||
t1 = QTime(14,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 <= t2) );
|
||||
|
||||
t1 = QTime(13,44,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 <= t2) );
|
||||
|
||||
t1 = QTime(13,34,56,20);
|
||||
t2 = QTime(13,34,46,20);
|
||||
QVERIFY( !(t1 <= t2) );
|
||||
|
||||
t1 = QTime(13,44,56,30);
|
||||
t2 = QTime(13,44,56,20);
|
||||
QVERIFY( !(t1 <= t2) );
|
||||
}
|
||||
|
||||
void tst_QTime::operator_gt_eq()
|
||||
{
|
||||
QTime t1(0,0,0,0);
|
||||
QTime t2(0,0,0,0);
|
||||
QVERIFY( t1 >= t2 );
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(12,34,56,30);
|
||||
QVERIFY( !(t1 >= t2) );
|
||||
|
||||
t1 = QTime(13,34,46,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 >= t2) );
|
||||
|
||||
t1 = QTime(13,24,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 >= t2) );
|
||||
|
||||
t1 = QTime(12,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( !(t1 >= t2) );
|
||||
|
||||
t1 = QTime(14,34,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 >= t2 );
|
||||
|
||||
t1 = QTime(13,44,56,20);
|
||||
t2 = QTime(13,34,56,20);
|
||||
QVERIFY( t1 >= t2 );
|
||||
|
||||
t1 = QTime(13,34,56,20);
|
||||
t2 = QTime(13,34,46,20);
|
||||
QVERIFY( t1 >= t2 );
|
||||
|
||||
t1 = QTime(13,44,56,30);
|
||||
t2 = QTime(13,44,56,20);
|
||||
QVERIFY( t1 >= t2 );
|
||||
QTestPrivate::testAllComparisonOperators(left, right, expectedOrdering);
|
||||
}
|
||||
|
||||
#if QT_CONFIG(datestring)
|
||||
|
Loading…
x
Reference in New Issue
Block a user