diff options
Diffstat (limited to 'tests/auto/corelib/tools/qline/tst_qline.cpp')
-rw-r--r-- | tests/auto/corelib/tools/qline/tst_qline.cpp | 328 |
1 files changed, 211 insertions, 117 deletions
diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp index 31aa5b4e0c..10069e821b 100644 --- a/tests/auto/corelib/tools/qline/tst_qline.cpp +++ b/tests/auto/corelib/tools/qline/tst_qline.cpp @@ -1,43 +1,27 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include <qline.h> -#include <math.h> +#include <qmath.h> +#include <private/qcomparisontesthelper_p.h> -#ifndef M_2PI -#define M_2PI 6.28318530717958647692528676655900576 -#endif +#include <array> class tst_QLine : public QObject { Q_OBJECT private slots: + void testComparisonCompiles(); + void testComparison_data(); + void testComparison(); + + void testFuzzyCompare_data(); + void testFuzzyCompare(); + + void testIsNull_data(); + void testIsNull(); + void testIntersection(); void testIntersection_data(); @@ -53,11 +37,6 @@ private slots: void testNormalVector(); void testNormalVector_data(); -#if QT_DEPRECATED_SINCE(5, 14) - void testAngle(); - void testAngle_data(); -#endif - void testAngle2(); void testAngle2_data(); @@ -67,15 +46,126 @@ private slots: void testAngleTo_data(); void testSet(); + + void toLineF_data(); + void toLineF(); }; -// Square root of two -#define SQRT2 1.4142135623731 +const qreal epsilon = sizeof(qreal) == sizeof(double) ? 1e-8 : 1e-4; +constexpr static qreal qreal_min = std::numeric_limits<qreal>::min(); -// Length of unit vector projected to x from 45 degrees -#define UNITX_45 0.707106781186547 +void tst_QLine::testComparisonCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile<QLine>(); + QTestPrivate::testEqualityOperatorsCompile<QLineF>(); + QTestPrivate::testEqualityOperatorsCompile<QLineF, QLine>(); +} -const qreal epsilon = sizeof(qreal) == sizeof(double) ? 1e-8 : 1e-4; +void tst_QLine::testComparison_data() +{ + QTest::addColumn<double>("xa1"); + QTest::addColumn<double>("ya1"); + QTest::addColumn<double>("xa2"); + QTest::addColumn<double>("ya2"); + QTest::addColumn<double>("xb1"); + QTest::addColumn<double>("yb1"); + QTest::addColumn<double>("xb2"); + QTest::addColumn<double>("yb2"); + QTest::addColumn<bool>("result"); + QTest::addColumn<bool>("floatResult"); + QTest::addColumn<bool>("mixedResult"); + + auto row = [&](double xa1, double ya1, double xa2, double ya2, + double xb1, double yb1, double xb2, double yb2, + bool result, bool floatResult, bool mixedResult) + { + QString str; + QDebug dbg(&str); + dbg.nospace() << "[(" << xa1 << ", " << ya1 << "); (" << xa2 << ", " << ya2 << ")] vs [(" + << xb1 << ", " << yb1 << "); (" << xb2 << ", " << yb2 << ")]"; + QTest::addRow("%s", str.toLatin1().constData()) + << xa1 << ya1 << xa2 << ya2 << xb1 << yb1 << xb2 << yb2 + << result << floatResult << mixedResult; + }; + + row(-1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, true, true, true); + row(-1.1, -0.9, 1.1, 0.9, -1.0, -1.0, 1.0, 1.0, true, false, false); + row(-1.0, -1.0, 1.0, 1.0, -0.9, -1.1, 0.9, 1.1, true, false, true); + row(-qreal_min, -1.0, 1.0, qreal_min, 0.0, -1.1, 0.9, 0.0, true, false, true); +} + +void tst_QLine::testComparison() +{ + QFETCH(double, xa1); + QFETCH(double, ya1); + QFETCH(double, xa2); + QFETCH(double, ya2); + QFETCH(double, xb1); + QFETCH(double, yb1); + QFETCH(double, xb2); + QFETCH(double, yb2); + QFETCH(bool, result); + QFETCH(bool, floatResult); + QFETCH(bool, mixedResult); + + const QLineF l1f(xa1, ya1, xa2, ya2); + const QLine l1 = l1f.toLine(); + + const QLineF l2f(xb1, yb1, xb2, yb2); + const QLine l2 = l2f.toLine(); + + QT_TEST_EQUALITY_OPS(l1, l2, result); + QT_TEST_EQUALITY_OPS(l1f, l2f, floatResult); + QT_TEST_EQUALITY_OPS(l1f, l2, mixedResult); +} + +void tst_QLine::testFuzzyCompare_data() +{ + testComparison_data(); +} + +void tst_QLine::testFuzzyCompare() +{ + QFETCH(double, xa1); + QFETCH(double, ya1); + QFETCH(double, xa2); + QFETCH(double, ya2); + QFETCH(double, xb1); + QFETCH(double, yb1); + QFETCH(double, xb2); + QFETCH(double, yb2); + QFETCH(bool, floatResult); + + const QLineF l1f(xa1, ya1, xa2, ya2); + const QLineF l2f(xb1, yb1, xb2, yb2); + + QCOMPARE_EQ(qFuzzyCompare(l1f, l2f), floatResult); +} + +void tst_QLine::testIsNull_data() +{ + QTest::addColumn<QLineF>("lineF"); + QTest::addColumn<bool>("result"); + QTest::addColumn<bool>("floatResult"); + + QTest::newRow("non-null") << QLineF(1.0, 1.0, 2.0, 2.0) << false << false; + QTest::newRow("null") << QLineF(1.0, 1.0, 1.0, 1.0) << true << true; + QTest::newRow("null_int_non-null_float") << QLineF(1.0, 1.0, 1.1, 1.1) << true << false; + QTest::newRow("with_qreal_min") << QLineF(-qreal_min, qreal_min, 0.0, 0.0) << true << true; +} + +void tst_QLine::testIsNull() +{ + QFETCH(QLineF, lineF); + QFETCH(bool, result); + QFETCH(bool, floatResult); + + const QLine line = lineF.toLine(); + + QCOMPARE_EQ(line.isNull(), result); + QCOMPARE_EQ(lineF.isNull(), floatResult); + QCOMPARE_EQ(qFuzzyIsNull(lineF), floatResult); +} void tst_QLine::testSet() { @@ -208,9 +298,6 @@ void tst_QLine::testIntersection() QPointF ip; QLineF::IntersectionType itype = a.intersects(b, &ip); -#if QT_DEPRECATED_SINCE(5, 14) - QCOMPARE(a.intersect(b, &ip), itype); -#endif QCOMPARE(int(itype), type); if (type != QLineF::NoIntersection) { @@ -230,30 +317,46 @@ void tst_QLine::testLength_data() QTest::addColumn<double>("vx"); QTest::addColumn<double>("vy"); - QTest::newRow("[1,0]*2") << 0.0 << 0.0 << 1.0 << 0.0 << 1.0 << 2.0 << 2.0 << 0.0; - QTest::newRow("[0,1]*2") << 0.0 << 0.0 << 0.0 << 1.0 << 1.0 << 2.0 << 0.0 << 2.0; - QTest::newRow("[-1,0]*2") << 0.0 << 0.0 << -1.0 << 0.0 << 1.0 << 2.0 << -2.0 << 0.0; - QTest::newRow("[0,-1]*2") << 0.0 << 0.0 << 0.0 << -1.0 << 1.0 << 2.0 << 0.0 << -2.0; - QTest::newRow("[1,1]->|1|") << 0.0 << 0.0 << 1.0 << 1.0 - << double(SQRT2) << 1.0 << double(UNITX_45) << double(UNITX_45); + // Test name: [dx,dy]->|lenToSet| (x1,x2) + // with the last part omitted if (0,0) + QTest::newRow("[1,0]->|2|") << 0.0 << 0.0 << 1.0 << 0.0 << 1.0 << 2.0 << 2.0 << 0.0; + QTest::newRow("[0,1]->|2|") << 0.0 << 0.0 << 0.0 << 1.0 << 1.0 << 2.0 << 0.0 << 2.0; + QTest::newRow("[-1,0]->|2|") << 0.0 << 0.0 << -1.0 << 0.0 << 1.0 << 2.0 << -2.0 << 0.0; + QTest::newRow("[0,-1]->|2|") << 0.0 << 0.0 << 0.0 << -1.0 << 1.0 << 2.0 << 0.0 << -2.0; + QTest::newRow("[1,1]->->|1|") << 0.0 << 0.0 << 1.0 << 1.0 + << M_SQRT2 << 1.0 << M_SQRT1_2 << M_SQRT1_2; QTest::newRow("[-1,1]->|1|") << 0.0 << 0.0 << -1.0 << 1.0 - << double(SQRT2) << 1.0 << double(-UNITX_45) << double(UNITX_45); + << M_SQRT2 << 1.0 << -M_SQRT1_2 << M_SQRT1_2; QTest::newRow("[1,-1]->|1|") << 0.0 << 0.0 << 1.0 << -1.0 - << double(SQRT2) << 1.0 << double(UNITX_45) << double(-UNITX_45); + << M_SQRT2 << 1.0 << M_SQRT1_2 << -M_SQRT1_2; QTest::newRow("[-1,-1]->|1|") << 0.0 << 0.0 << -1.0 << -1.0 - << double(SQRT2) << 1.0 << double(-UNITX_45) << double(-UNITX_45); - QTest::newRow("[1,0]*2 (2,2)") << 2.0 << 2.0 << 3.0 << 2.0 << 1.0 << 2.0 << 2.0 << 0.0; - QTest::newRow("[0,1]*2 (2,2)") << 2.0 << 2.0 << 2.0 << 3.0 << 1.0 << 2.0 << 0.0 << 2.0; - QTest::newRow("[-1,0]*2 (2,2)") << 2.0 << 2.0 << 1.0 << 2.0 << 1.0 << 2.0 << -2.0 << 0.0; - QTest::newRow("[0,-1]*2 (2,2)") << 2.0 << 2.0 << 2.0 << 1.0 << 1.0 << 2.0 << 0.0 << -2.0; + << M_SQRT2 << 1.0 << -M_SQRT1_2 << -M_SQRT1_2; + QTest::newRow("[1,0]->|2| (2,2)") << 2.0 << 2.0 << 3.0 << 2.0 << 1.0 << 2.0 << 2.0 << 0.0; + QTest::newRow("[0,1]->|2| (2,2)") << 2.0 << 2.0 << 2.0 << 3.0 << 1.0 << 2.0 << 0.0 << 2.0; + QTest::newRow("[-1,0]->|2| (2,2)") << 2.0 << 2.0 << 1.0 << 2.0 << 1.0 << 2.0 << -2.0 << 0.0; + QTest::newRow("[0,-1]->|2| (2,2)") << 2.0 << 2.0 << 2.0 << 1.0 << 1.0 << 2.0 << 0.0 << -2.0; QTest::newRow("[1,1]->|1| (2,2)") << 2.0 << 2.0 << 3.0 << 3.0 - << double(SQRT2) << 1.0 << double(UNITX_45) << double(UNITX_45); + << M_SQRT2 << 1.0 << M_SQRT1_2 << M_SQRT1_2; QTest::newRow("[-1,1]->|1| (2,2)") << 2.0 << 2.0 << 1.0 << 3.0 - << double(SQRT2) << 1.0 << double(-UNITX_45) << double(UNITX_45); + << M_SQRT2 << 1.0 << -M_SQRT1_2 << M_SQRT1_2; QTest::newRow("[1,-1]->|1| (2,2)") << 2.0 << 2.0 << 3.0 << 1.0 - << double(SQRT2) << 1.0 << double(UNITX_45) << double(-UNITX_45); + << M_SQRT2 << 1.0 << M_SQRT1_2 << -M_SQRT1_2; QTest::newRow("[-1,-1]->|1| (2,2)") << 2.0 << 2.0 << 1.0 << 1.0 - << double(SQRT2) << 1.0 << double(-UNITX_45) << double(-UNITX_45); + << M_SQRT2 << 1.0 << -M_SQRT1_2 << -M_SQRT1_2; + const double small = qSqrt(std::numeric_limits<qreal>::denorm_min()) / 8; + QTest::newRow("[small,small]->|2| (-small/2,-small/2)") + << -(small * .5) << -(small * .5) << (small * .5) << (small * .5) + << (small * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0; + const double tiny = std::numeric_limits<qreal>::min() / 2; + QTest::newRow("[tiny,tiny]->|2| (-tiny/2,-tiny/2)") + << -(tiny * .5) << -(tiny * .5) << (tiny * .5) << (tiny * .5) + << (tiny * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0; + QTest::newRow("[1+3e-13,1+4e-13]|1895| (1, 1)") + << 1.0 << 1.0 << (1 + 3e-13) << (1 + 4e-13) + << 5e-13 << 1895.0 << 1137.0 << 1516.0; + QTest::newRow("[4e-323,5e-324]|1892|") // Unavoidable underflow: denormals + << 0.0 << 0.0 << 4e-323 << 5e-324 + << 4e-323 << 1892.0 << 4e-323 << 5e-324; // vx, vy values ignored } void tst_QLine::testLength() @@ -271,9 +374,21 @@ void tst_QLine::testLength() QCOMPARE(l.length(), qreal(length)); l.setLength(lengthToSet); - QCOMPARE(l.length(), qreal(lengthToSet)); - QCOMPARE(l.dx(), qreal(vx)); - QCOMPARE(l.dy(), qreal(vy)); + + if constexpr (std::numeric_limits<double>::has_denorm != std::denorm_present) { + if (qstrcmp(QTest::currentDataTag(), "[tiny,tiny]->|2| (-tiny/2,-tiny/2)") == 0 + || qstrcmp(QTest::currentDataTag(), "[4e-323,5e-324]|1892|") == 0) { + QSKIP("Skipping 'denorm' as this type lacks denormals on this system"); + } + } + // Scaling tiny values up to big can be imprecise: don't try to test vx, vy + if (length > 0 && qFuzzyIsNull(length)) { + QVERIFY(l.length() > lengthToSet / 2 && l.length() < lengthToSet * 2); + } else { + QCOMPARE(l.length(), length > 0 ? qreal(lengthToSet) : qreal(length)); + QCOMPARE(l.dx(), qreal(vx)); + QCOMPARE(l.dy(), qreal(vy)); + } } void tst_QLine::testCenter() @@ -383,57 +498,6 @@ void tst_QLine::testNormalVector() QCOMPARE(n.dy(), qreal(nvy)); } -#if QT_DEPRECATED_SINCE(5, 14) -void tst_QLine::testAngle_data() -{ - QTest::addColumn<double>("xa1"); - QTest::addColumn<double>("ya1"); - QTest::addColumn<double>("xa2"); - QTest::addColumn<double>("ya2"); - QTest::addColumn<double>("xb1"); - QTest::addColumn<double>("yb1"); - QTest::addColumn<double>("xb2"); - QTest::addColumn<double>("yb2"); - QTest::addColumn<double>("angle"); - - QTest::newRow("parallel") << 1.0 << 1.0 << 3.0 << 4.0 - << 5.0 << 6.0 << 7.0 << 9.0 - << 0.0; - QTest::newRow("[4,4]-[4,0]") << 1.0 << 1.0 << 5.0 << 5.0 - << 0.0 << 4.0 << 3.0 << 4.0 - << 45.0; - QTest::newRow("[4,4]-[-4,0]") << 1.0 << 1.0 << 5.0 << 5.0 - << 3.0 << 4.0 << 0.0 << 4.0 - << 135.0; - - for (int i=0; i<180; ++i) { - QTest::newRow(("angle:" + QByteArray::number(i)).constData()) - << 0.0 << 0.0 << double(cos(i*M_2PI/360)) << double(sin(i*M_2PI/360)) - << 0.0 << 0.0 << 1.0 << 0.0 - << double(i); - } -} - -void tst_QLine::testAngle() -{ - QFETCH(double, xa1); - QFETCH(double, ya1); - QFETCH(double, xa2); - QFETCH(double, ya2); - QFETCH(double, xb1); - QFETCH(double, yb1); - QFETCH(double, xb2); - QFETCH(double, yb2); - QFETCH(double, angle); - - QLineF a(xa1, ya1, xa2, ya2); - QLineF b(xb1, yb1, xb2, yb2); - - double resultAngle = a.angle(b); - QCOMPARE(qRound(resultAngle), qRound(angle)); -} -#endif - void tst_QLine::testAngle2_data() { QTest::addColumn<qreal>("x1"); @@ -543,5 +607,35 @@ void tst_QLine::testAngleTo_data() } } +void tst_QLine::toLineF_data() +{ + QTest::addColumn<QLine>("input"); + QTest::addColumn<QLineF>("result"); + + auto row = [](int x1, int y1, int x2, int y2) { + QTest::addRow("((%d, %d)->(%d, %d))", x1, y1, x2, y2) + << QLine(x1, y1, x2, y2) << QLineF(x1, y1, x2, y2); + }; + constexpr std::array samples = {-1, 0, 1}; + for (int x1 : samples) { + for (int y1 : samples) { + for (int x2 : samples) { + for (int y2 : samples) { + row(x1, y1, x2, y2); + } + } + } + } +} + +void tst_QLine::toLineF() +{ + QFETCH(const QLine, input); + QFETCH(const QLineF, result); + + QCOMPARE(input.toLineF(), result); +} + + QTEST_MAIN(tst_QLine) #include "tst_qline.moc" |