diff options
Diffstat (limited to 'tests/auto/corelib/global')
50 files changed, 3611 insertions, 892 deletions
diff --git a/tests/auto/corelib/global/CMakeLists.txt b/tests/auto/corelib/global/CMakeLists.txt index fe63402288..7970116672 100644 --- a/tests/auto/corelib/global/CMakeLists.txt +++ b/tests/auto/corelib/global/CMakeLists.txt @@ -1,7 +1,10 @@ -# Generated from global.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + if(NOT INTEGRITY) add_subdirectory(qcompare) endif() +add_subdirectory(qcomparehelpers) add_subdirectory(qflags) add_subdirectory(q_func_info) add_subdirectory(qgetputenv) @@ -18,6 +21,5 @@ add_subdirectory(qtendian) add_subdirectory(qglobalstatic) add_subdirectory(qhooks) add_subdirectory(qoperatingsystemversion) -if(WIN32) - add_subdirectory(qwinregistry) -endif() +add_subdirectory(qxp) +add_subdirectory(q20) diff --git a/tests/auto/corelib/global/q20/CMakeLists.txt b/tests/auto/corelib/global/q20/CMakeLists.txt new file mode 100644 index 0000000000..bd28f8b999 --- /dev/null +++ b/tests/auto/corelib/global/q20/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(memory) diff --git a/tests/auto/corelib/global/q20/memory/CMakeLists.txt b/tests/auto/corelib/global/q20/memory/CMakeLists.txt new file mode 100644 index 0000000000..f36ff0f592 --- /dev/null +++ b/tests/auto/corelib/global/q20/memory/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_q20_memory LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_q20_memory + EXCEPTIONS + SOURCES + tst_q20_memory.cpp + LIBRARIES + Qt::Core +) diff --git a/tests/auto/corelib/global/q20/memory/tst_q20_memory.cpp b/tests/auto/corelib/global/q20/memory/tst_q20_memory.cpp new file mode 100644 index 0000000000..22dbb09e7c --- /dev/null +++ b/tests/auto/corelib/global/q20/memory/tst_q20_memory.cpp @@ -0,0 +1,161 @@ +// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <q20memory.h> +#include <QtCore/q20memory.h> + +#include <QTest> +#include <QObject> +#include <QExplicitlySharedDataPointer> +#include <QSharedDataPointer> + +struct Private : QSharedData {}; + +class tst_q20_memory : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void raw(); + void smart(); + void recursion(); + void usesPointerTraits(); + void prefersPointerTraits(); + +private Q_SLOTS: + void to_address_broken_const_propagation_QExplicitlySharedDataPointer() + { to_address_broken_const_propagation<QExplicitlySharedDataPointer<Private>>(); } + void to_address_broken_const_propagation_QSharedDataPointer() + { to_address_broken_const_propagation<QSharedDataPointer<Private>>(); } + void to_address_broken_const_propagation_shared_ptr() + { to_address_broken_const_propagation<std::shared_ptr<Private>>(); } + void to_address_broken_const_propagation_unique_ptr() + { to_address_broken_const_propagation<std::unique_ptr<Private>>(); } + +private: + template <typename Pointer> + void to_address_broken_const_propagation(); +}; + +void tst_q20_memory::raw() +{ + auto i = 0; + auto p = &i; + QVERIFY(q20::to_address(p) == &i); +} + +template <typename T> +class MinimalPtr { +public: + using element_type = T; + + explicit MinimalPtr(T *d) : d(d) {} + + T *operator->() const noexcept { return d; } + +private: + T *d; +}; + +void tst_q20_memory::smart() +{ + int i; + MinimalPtr ptr(&i); + QCOMPARE_EQ(q20::to_address(ptr), &i); +} + +template <typename T> +class RecursivePtr { +public: + using element_type = T; + + explicit RecursivePtr(T *d) : d(d) {} + + MinimalPtr<T> operator->() const noexcept { return d; } + +private: + MinimalPtr<T> d; +}; + +void tst_q20_memory::recursion() +{ + int i; + RecursivePtr ptr(&i); + QCOMPARE_EQ(q20::to_address(ptr), &i); +} + +template <typename T> +class NoDerefOperatorPtr { +public: + using element_type = T; + + explicit NoDerefOperatorPtr(T *d) : d(d) {} + + T *get() const noexcept { return d; } + +private: + T *d; +}; + +namespace std { +template <typename T> +struct pointer_traits<NoDerefOperatorPtr<T>> +{ + static T *to_address(const NoDerefOperatorPtr<T> &ptr) noexcept { return ptr.get(); } +}; +} // namespace std + +void tst_q20_memory::usesPointerTraits() +{ + int i; + NoDerefOperatorPtr ptr(&i); + QCOMPARE_EQ(q20::to_address(ptr), &i); +} + +template <typename T> +class PrefersPointerTraitsPtr +{ +public: + using element_type = T; + + explicit PrefersPointerTraitsPtr(T *d) : d(d) {} + + T *operator->() const noexcept { return nullptr; } + + T *get() const noexcept { return d; } + +private: + T *d; +}; + +namespace std { +template <typename T> +struct pointer_traits<PrefersPointerTraitsPtr<T>> +{ + static T *to_address(const PrefersPointerTraitsPtr<T> &p) noexcept { return p.get(); } +}; +} // namespace std + +void tst_q20_memory::prefersPointerTraits() +{ + int i; + PrefersPointerTraitsPtr ptr(&i); + QCOMPARE_EQ(q20::to_address(ptr), &i); +} + +template <typename Pointer> +void tst_q20_memory::to_address_broken_const_propagation() +{ + Pointer p(nullptr); + QCOMPARE_EQ(q20::to_address(p), nullptr); + p = Pointer{new Private()}; + QCOMPARE_EQ(q20::to_address(p), p.operator->()); + static_assert(std::is_same_v<decltype(q20::to_address(p)), + decltype(std::as_const(p).operator->())>); +} + +QTEST_GUILESS_MAIN(tst_q20_memory) +#include "tst_q20_memory.moc" + diff --git a/tests/auto/corelib/global/q_func_info/CMakeLists.txt b/tests/auto/corelib/global/q_func_info/CMakeLists.txt index 93257c31de..88119484cd 100644 --- a/tests/auto/corelib/global/q_func_info/CMakeLists.txt +++ b/tests/auto/corelib/global/q_func_info/CMakeLists.txt @@ -1,9 +1,16 @@ -# Generated from q_func_info.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_q_func_info Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_q_func_info LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_q_func_info SOURCES tst_q_func_info.cpp diff --git a/tests/auto/corelib/global/q_func_info/tst_q_func_info.cpp b/tests/auto/corelib/global/q_func_info/tst_q_func_info.cpp index 9d6bc15d73..b288f1d3a1 100644 --- a/tests/auto/corelib/global/q_func_info/tst_q_func_info.cpp +++ b/tests/auto/corelib/global/q_func_info/tst_q_func_info.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QString> diff --git a/tests/auto/corelib/global/qcompare/CMakeLists.txt b/tests/auto/corelib/global/qcompare/CMakeLists.txt index 0fbf696d0e..b29dcae618 100644 --- a/tests/auto/corelib/global/qcompare/CMakeLists.txt +++ b/tests/auto/corelib/global/qcompare/CMakeLists.txt @@ -1,9 +1,16 @@ -# Generated from qcompare.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcompare Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcompare LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcompare SOURCES tst_qcompare.cpp diff --git a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp index 61ea0eddc4..e36429e62b 100644 --- a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp +++ b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp @@ -1,54 +1,36 @@ -/**************************************************************************** -** -** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QtCompare> #include <QtTest/QTest> +#ifdef __cpp_lib_three_way_comparison +#include <compare> +#endif // __cpp_lib_three_way_comparison + class tst_QCompare: public QObject { Q_OBJECT private slots: + void legacyPartialOrdering(); + void legacyConversions(); + void stdQtBinaryCompatibility(); void partialOrdering(); + void weakOrdering(); + void strongOrdering(); + void threeWayCompareWithLiteralZero(); + void conversions(); + void is_eq_overloads(); + void compareThreeWay(); }; -void tst_QCompare::partialOrdering() +void tst_QCompare::legacyPartialOrdering() { + static_assert(QPartialOrdering::Unordered == QPartialOrdering::unordered); + static_assert(QPartialOrdering::Less == QPartialOrdering::less); + static_assert(QPartialOrdering::Equivalent == QPartialOrdering::equivalent); + static_assert(QPartialOrdering::Greater == QPartialOrdering::greater); + static_assert(QPartialOrdering::Unordered == QPartialOrdering::Unordered); static_assert(QPartialOrdering::Unordered != QPartialOrdering::Less); static_assert(QPartialOrdering::Unordered != QPartialOrdering::Equivalent); @@ -69,6 +51,12 @@ void tst_QCompare::partialOrdering() static_assert(QPartialOrdering::Greater != QPartialOrdering::Equivalent); static_assert(QPartialOrdering::Greater == QPartialOrdering::Greater); + static_assert(!is_eq (QPartialOrdering::Unordered)); + static_assert(!is_neq (QPartialOrdering::Unordered)); + static_assert(!is_lt (QPartialOrdering::Unordered)); + static_assert(!is_lteq(QPartialOrdering::Unordered)); + static_assert(!is_gt (QPartialOrdering::Unordered)); + static_assert(!is_gteq(QPartialOrdering::Unordered)); static_assert(!(QPartialOrdering::Unordered == 0)); static_assert(!(QPartialOrdering::Unordered != 0)); @@ -85,6 +73,13 @@ void tst_QCompare::partialOrdering() static_assert(!(0 >= QPartialOrdering::Unordered)); + static_assert(!is_eq (QPartialOrdering::Less)); + static_assert( is_neq (QPartialOrdering::Less)); + static_assert( is_lt (QPartialOrdering::Less)); + static_assert( is_lteq(QPartialOrdering::Less)); + static_assert(!is_gt (QPartialOrdering::Less)); + static_assert(!is_gteq(QPartialOrdering::Less)); + static_assert(!(QPartialOrdering::Less == 0)); static_assert( (QPartialOrdering::Less != 0)); static_assert( (QPartialOrdering::Less < 0)); @@ -100,6 +95,13 @@ void tst_QCompare::partialOrdering() static_assert( (0 >= QPartialOrdering::Less)); + static_assert( is_eq (QPartialOrdering::Equivalent)); + static_assert(!is_neq (QPartialOrdering::Equivalent)); + static_assert(!is_lt (QPartialOrdering::Equivalent)); + static_assert( is_lteq(QPartialOrdering::Equivalent)); + static_assert(!is_gt (QPartialOrdering::Equivalent)); + static_assert( is_gteq(QPartialOrdering::Equivalent)); + static_assert( (QPartialOrdering::Equivalent == 0)); static_assert(!(QPartialOrdering::Equivalent != 0)); static_assert(!(QPartialOrdering::Equivalent < 0)); @@ -115,6 +117,13 @@ void tst_QCompare::partialOrdering() static_assert( (0 >= QPartialOrdering::Equivalent)); + static_assert(!is_eq (QPartialOrdering::Greater)); + static_assert( is_neq (QPartialOrdering::Greater)); + static_assert(!is_lt (QPartialOrdering::Greater)); + static_assert(!is_lteq(QPartialOrdering::Greater)); + static_assert( is_gt (QPartialOrdering::Greater)); + static_assert( is_gteq(QPartialOrdering::Greater)); + static_assert(!(QPartialOrdering::Greater == 0)); static_assert( (QPartialOrdering::Greater != 0)); static_assert(!(QPartialOrdering::Greater < 0)); @@ -130,5 +139,702 @@ void tst_QCompare::partialOrdering() static_assert(!(0 >= QPartialOrdering::Greater)); } +void tst_QCompare::legacyConversions() +{ +#define CHECK_CONVERTS(Lhs, Rhs) static_assert(std::is_convertible_v<Lhs, Rhs>) +#define CHECK_ALL(NS) do { \ + CHECK_CONVERTS(QPartialOrdering, NS ::partial_ordering); \ + static_assert(QPartialOrdering::Less == NS ::partial_ordering::less); \ + static_assert(QPartialOrdering::Greater == NS ::partial_ordering::greater); \ + static_assert(QPartialOrdering::Equivalent == NS ::partial_ordering::equivalent); \ + static_assert(QPartialOrdering::Unordered == NS ::partial_ordering::unordered); \ + \ + CHECK_CONVERTS(NS ::partial_ordering, QPartialOrdering); \ + CHECK_CONVERTS(NS ::weak_ordering, QPartialOrdering); \ + CHECK_CONVERTS(NS ::strong_ordering, QPartialOrdering); \ + } while (false) + + CHECK_ALL(Qt); +#ifdef __cpp_lib_three_way_comparison + CHECK_ALL(std); +#endif // __cpp_lib_three_way_comparison + +#undef CHECK_ALL +#undef CHECK_CONVERTS +} + +void tst_QCompare::stdQtBinaryCompatibility() +{ +#ifndef __cpp_lib_three_way_comparison + QSKIP("This test requires C++20 three-way-comparison support enabled in the stdlib."); +#else + QCOMPARE_EQ(sizeof(std::partial_ordering), 1U); + QCOMPARE_EQ(sizeof( Qt::partial_ordering), 1U); + QCOMPARE_EQ(sizeof(std:: weak_ordering), 1U); + QCOMPARE_EQ(sizeof( Qt:: weak_ordering), 1U); + QCOMPARE_EQ(sizeof(std:: strong_ordering), 1U); + QCOMPARE_EQ(sizeof( Qt:: strong_ordering), 1U); + + auto valueOf = [](auto obj) { + typename QIntegerForSizeof<decltype(obj)>::Unsigned value; + memcpy(&value, &obj, sizeof(obj)); + return value; + }; +#define CHECK(type, flag) \ + QCOMPARE_EQ(valueOf( Qt:: type ## _ordering :: flag), \ + valueOf(std:: type ## _ordering :: flag)) \ + /* end */ + CHECK(partial, unordered); + CHECK(partial, less); + CHECK(partial, greater); + CHECK(partial, equivalent); + + CHECK(weak, less); + CHECK(weak, greater); + CHECK(weak, equivalent); + + CHECK(strong, less); + CHECK(strong, greater); + CHECK(strong, equivalent); + CHECK(strong, equal); +#undef CHECK +#endif //__cpp_lib_three_way_comparison +} + +void tst_QCompare::partialOrdering() +{ + static_assert(Qt::partial_ordering::unordered == Qt::partial_ordering::unordered); + static_assert(Qt::partial_ordering::unordered != Qt::partial_ordering::less); + static_assert(Qt::partial_ordering::unordered != Qt::partial_ordering::equivalent); + static_assert(Qt::partial_ordering::unordered != Qt::partial_ordering::greater); + + static_assert(Qt::partial_ordering::less != Qt::partial_ordering::unordered); + static_assert(Qt::partial_ordering::less == Qt::partial_ordering::less); + static_assert(Qt::partial_ordering::less != Qt::partial_ordering::equivalent); + static_assert(Qt::partial_ordering::less != Qt::partial_ordering::greater); + + static_assert(Qt::partial_ordering::equivalent != Qt::partial_ordering::unordered); + static_assert(Qt::partial_ordering::equivalent != Qt::partial_ordering::less); + static_assert(Qt::partial_ordering::equivalent == Qt::partial_ordering::equivalent); + static_assert(Qt::partial_ordering::equivalent != Qt::partial_ordering::greater); + + static_assert(Qt::partial_ordering::greater != Qt::partial_ordering::unordered); + static_assert(Qt::partial_ordering::greater != Qt::partial_ordering::less); + static_assert(Qt::partial_ordering::greater != Qt::partial_ordering::equivalent); + static_assert(Qt::partial_ordering::greater == Qt::partial_ordering::greater); + + static_assert(!is_eq (Qt::partial_ordering::unordered)); + static_assert(!is_neq (Qt::partial_ordering::unordered)); + static_assert(!is_lt (Qt::partial_ordering::unordered)); + static_assert(!is_lteq(Qt::partial_ordering::unordered)); + static_assert(!is_gt (Qt::partial_ordering::unordered)); + static_assert(!is_gteq(Qt::partial_ordering::unordered)); + + static_assert(!(Qt::partial_ordering::unordered == 0)); + static_assert(!(Qt::partial_ordering::unordered != 0)); + static_assert(!(Qt::partial_ordering::unordered < 0)); + static_assert(!(Qt::partial_ordering::unordered <= 0)); + static_assert(!(Qt::partial_ordering::unordered > 0)); + static_assert(!(Qt::partial_ordering::unordered >= 0)); + + static_assert(!(0 == Qt::partial_ordering::unordered)); + static_assert(!(0 != Qt::partial_ordering::unordered)); + static_assert(!(0 < Qt::partial_ordering::unordered)); + static_assert(!(0 <= Qt::partial_ordering::unordered)); + static_assert(!(0 > Qt::partial_ordering::unordered)); + static_assert(!(0 >= Qt::partial_ordering::unordered)); + + + static_assert(!is_eq (Qt::partial_ordering::less)); + static_assert( is_neq (Qt::partial_ordering::less)); + static_assert( is_lt (Qt::partial_ordering::less)); + static_assert( is_lteq(Qt::partial_ordering::less)); + static_assert(!is_gt (Qt::partial_ordering::less)); + static_assert(!is_gteq(Qt::partial_ordering::less)); + + static_assert(!(Qt::partial_ordering::less == 0)); + static_assert( (Qt::partial_ordering::less != 0)); + static_assert( (Qt::partial_ordering::less < 0)); + static_assert( (Qt::partial_ordering::less <= 0)); + static_assert(!(Qt::partial_ordering::less > 0)); + static_assert(!(Qt::partial_ordering::less >= 0)); + + static_assert(!(0 == Qt::partial_ordering::less)); + static_assert( (0 != Qt::partial_ordering::less)); + static_assert(!(0 < Qt::partial_ordering::less)); + static_assert(!(0 <= Qt::partial_ordering::less)); + static_assert( (0 > Qt::partial_ordering::less)); + static_assert( (0 >= Qt::partial_ordering::less)); + + + static_assert( is_eq (Qt::partial_ordering::equivalent)); + static_assert(!is_neq (Qt::partial_ordering::equivalent)); + static_assert(!is_lt (Qt::partial_ordering::equivalent)); + static_assert( is_lteq(Qt::partial_ordering::equivalent)); + static_assert(!is_gt (Qt::partial_ordering::equivalent)); + static_assert( is_gteq(Qt::partial_ordering::equivalent)); + + static_assert( (Qt::partial_ordering::equivalent == 0)); + static_assert(!(Qt::partial_ordering::equivalent != 0)); + static_assert(!(Qt::partial_ordering::equivalent < 0)); + static_assert( (Qt::partial_ordering::equivalent <= 0)); + static_assert(!(Qt::partial_ordering::equivalent > 0)); + static_assert( (Qt::partial_ordering::equivalent >= 0)); + + static_assert( (0 == Qt::partial_ordering::equivalent)); + static_assert(!(0 != Qt::partial_ordering::equivalent)); + static_assert(!(0 < Qt::partial_ordering::equivalent)); + static_assert( (0 <= Qt::partial_ordering::equivalent)); + static_assert(!(0 > Qt::partial_ordering::equivalent)); + static_assert( (0 >= Qt::partial_ordering::equivalent)); + + + static_assert(!is_eq (Qt::partial_ordering::greater)); + static_assert( is_neq (Qt::partial_ordering::greater)); + static_assert(!is_lt (Qt::partial_ordering::greater)); + static_assert(!is_lteq(Qt::partial_ordering::greater)); + static_assert( is_gt (Qt::partial_ordering::greater)); + static_assert( is_gteq(Qt::partial_ordering::greater)); + + static_assert(!(Qt::partial_ordering::greater == 0)); + static_assert( (Qt::partial_ordering::greater != 0)); + static_assert(!(Qt::partial_ordering::greater < 0)); + static_assert(!(Qt::partial_ordering::greater <= 0)); + static_assert( (Qt::partial_ordering::greater > 0)); + static_assert( (Qt::partial_ordering::greater >= 0)); + + static_assert(!(0 == Qt::partial_ordering::greater)); + static_assert( (0 != Qt::partial_ordering::greater)); + static_assert( (0 < Qt::partial_ordering::greater)); + static_assert( (0 <= Qt::partial_ordering::greater)); + static_assert(!(0 > Qt::partial_ordering::greater)); + static_assert(!(0 >= Qt::partial_ordering::greater)); +} + +void tst_QCompare::weakOrdering() +{ + static_assert(Qt::weak_ordering::less == Qt::weak_ordering::less); + static_assert(Qt::weak_ordering::less != Qt::weak_ordering::equivalent); + static_assert(Qt::weak_ordering::less != Qt::weak_ordering::greater); + + static_assert(Qt::weak_ordering::equivalent != Qt::weak_ordering::less); + static_assert(Qt::weak_ordering::equivalent == Qt::weak_ordering::equivalent); + static_assert(Qt::weak_ordering::equivalent != Qt::weak_ordering::greater); + + static_assert(Qt::weak_ordering::greater != Qt::weak_ordering::less); + static_assert(Qt::weak_ordering::greater != Qt::weak_ordering::equivalent); + static_assert(Qt::weak_ordering::greater == Qt::weak_ordering::greater); + + static_assert(!is_eq (Qt::weak_ordering::less)); + static_assert( is_neq (Qt::weak_ordering::less)); + static_assert( is_lt (Qt::weak_ordering::less)); + static_assert( is_lteq(Qt::weak_ordering::less)); + static_assert(!is_gt (Qt::weak_ordering::less)); + static_assert(!is_gteq(Qt::weak_ordering::less)); + + static_assert(!(Qt::weak_ordering::less == 0)); + static_assert( (Qt::weak_ordering::less != 0)); + static_assert( (Qt::weak_ordering::less < 0)); + static_assert( (Qt::weak_ordering::less <= 0)); + static_assert(!(Qt::weak_ordering::less > 0)); + static_assert(!(Qt::weak_ordering::less >= 0)); + + static_assert(!(0 == Qt::weak_ordering::less)); + static_assert( (0 != Qt::weak_ordering::less)); + static_assert(!(0 < Qt::weak_ordering::less)); + static_assert(!(0 <= Qt::weak_ordering::less)); + static_assert( (0 > Qt::weak_ordering::less)); + static_assert( (0 >= Qt::weak_ordering::less)); + + + static_assert( is_eq (Qt::weak_ordering::equivalent)); + static_assert(!is_neq (Qt::weak_ordering::equivalent)); + static_assert(!is_lt (Qt::weak_ordering::equivalent)); + static_assert( is_lteq(Qt::weak_ordering::equivalent)); + static_assert(!is_gt (Qt::weak_ordering::equivalent)); + static_assert( is_gteq(Qt::weak_ordering::equivalent)); + + static_assert( (Qt::weak_ordering::equivalent == 0)); + static_assert(!(Qt::weak_ordering::equivalent != 0)); + static_assert(!(Qt::weak_ordering::equivalent < 0)); + static_assert( (Qt::weak_ordering::equivalent <= 0)); + static_assert(!(Qt::weak_ordering::equivalent > 0)); + static_assert( (Qt::weak_ordering::equivalent >= 0)); + + static_assert( (0 == Qt::weak_ordering::equivalent)); + static_assert(!(0 != Qt::weak_ordering::equivalent)); + static_assert(!(0 < Qt::weak_ordering::equivalent)); + static_assert( (0 <= Qt::weak_ordering::equivalent)); + static_assert(!(0 > Qt::weak_ordering::equivalent)); + static_assert( (0 >= Qt::weak_ordering::equivalent)); + + + static_assert(!is_eq (Qt::weak_ordering::greater)); + static_assert( is_neq (Qt::weak_ordering::greater)); + static_assert(!is_lt (Qt::weak_ordering::greater)); + static_assert(!is_lteq(Qt::weak_ordering::greater)); + static_assert( is_gt (Qt::weak_ordering::greater)); + static_assert( is_gteq(Qt::weak_ordering::greater)); + + static_assert(!(Qt::weak_ordering::greater == 0)); + static_assert( (Qt::weak_ordering::greater != 0)); + static_assert(!(Qt::weak_ordering::greater < 0)); + static_assert(!(Qt::weak_ordering::greater <= 0)); + static_assert( (Qt::weak_ordering::greater > 0)); + static_assert( (Qt::weak_ordering::greater >= 0)); + + static_assert(!(0 == Qt::weak_ordering::greater)); + static_assert( (0 != Qt::weak_ordering::greater)); + static_assert( (0 < Qt::weak_ordering::greater)); + static_assert( (0 <= Qt::weak_ordering::greater)); + static_assert(!(0 > Qt::weak_ordering::greater)); + static_assert(!(0 >= Qt::weak_ordering::greater)); +} + +void tst_QCompare::strongOrdering() +{ + static_assert(Qt::strong_ordering::less == Qt::strong_ordering::less); + static_assert(Qt::strong_ordering::less != Qt::strong_ordering::equal); + static_assert(Qt::strong_ordering::less != Qt::strong_ordering::equivalent); + static_assert(Qt::strong_ordering::less != Qt::strong_ordering::greater); + + static_assert(Qt::strong_ordering::equal != Qt::strong_ordering::less); + static_assert(Qt::strong_ordering::equal == Qt::strong_ordering::equal); + static_assert(Qt::strong_ordering::equal == Qt::strong_ordering::equivalent); + static_assert(Qt::strong_ordering::equal != Qt::strong_ordering::greater); + + static_assert(Qt::strong_ordering::equivalent != Qt::strong_ordering::less); + static_assert(Qt::strong_ordering::equivalent == Qt::strong_ordering::equal); + static_assert(Qt::strong_ordering::equivalent == Qt::strong_ordering::equivalent); + static_assert(Qt::strong_ordering::equivalent != Qt::strong_ordering::greater); + + static_assert(Qt::strong_ordering::greater != Qt::strong_ordering::less); + static_assert(Qt::strong_ordering::greater != Qt::strong_ordering::equal); + static_assert(Qt::strong_ordering::greater != Qt::strong_ordering::equivalent); + static_assert(Qt::strong_ordering::greater == Qt::strong_ordering::greater); + + static_assert(!is_eq (Qt::strong_ordering::less)); + static_assert( is_neq (Qt::strong_ordering::less)); + static_assert( is_lt (Qt::strong_ordering::less)); + static_assert( is_lteq(Qt::strong_ordering::less)); + static_assert(!is_gt (Qt::strong_ordering::less)); + static_assert(!is_gteq(Qt::strong_ordering::less)); + + static_assert(!(Qt::strong_ordering::less == 0)); + static_assert( (Qt::strong_ordering::less != 0)); + static_assert( (Qt::strong_ordering::less < 0)); + static_assert( (Qt::strong_ordering::less <= 0)); + static_assert(!(Qt::strong_ordering::less > 0)); + static_assert(!(Qt::strong_ordering::less >= 0)); + + static_assert(!(0 == Qt::strong_ordering::less)); + static_assert( (0 != Qt::strong_ordering::less)); + static_assert(!(0 < Qt::strong_ordering::less)); + static_assert(!(0 <= Qt::strong_ordering::less)); + static_assert( (0 > Qt::strong_ordering::less)); + static_assert( (0 >= Qt::strong_ordering::less)); + + + static_assert( is_eq (Qt::strong_ordering::equal)); + static_assert(!is_neq (Qt::strong_ordering::equal)); + static_assert(!is_lt (Qt::strong_ordering::equal)); + static_assert( is_lteq(Qt::strong_ordering::equal)); + static_assert(!is_gt (Qt::strong_ordering::equal)); + static_assert( is_gteq(Qt::strong_ordering::equal)); + + static_assert( (Qt::strong_ordering::equal == 0)); + static_assert(!(Qt::strong_ordering::equal != 0)); + static_assert(!(Qt::strong_ordering::equal < 0)); + static_assert( (Qt::strong_ordering::equal <= 0)); + static_assert(!(Qt::strong_ordering::equal > 0)); + static_assert( (Qt::strong_ordering::equal >= 0)); + + static_assert( (0 == Qt::strong_ordering::equal)); + static_assert(!(0 != Qt::strong_ordering::equal)); + static_assert(!(0 < Qt::strong_ordering::equal)); + static_assert( (0 <= Qt::strong_ordering::equal)); + static_assert(!(0 > Qt::strong_ordering::equal)); + static_assert( (0 >= Qt::strong_ordering::equal)); + + + static_assert( is_eq (Qt::strong_ordering::equivalent)); + static_assert(!is_neq (Qt::strong_ordering::equivalent)); + static_assert(!is_lt (Qt::strong_ordering::equivalent)); + static_assert( is_lteq(Qt::strong_ordering::equivalent)); + static_assert(!is_gt (Qt::strong_ordering::equivalent)); + static_assert( is_gteq(Qt::strong_ordering::equivalent)); + + static_assert( (Qt::strong_ordering::equivalent == 0)); + static_assert(!(Qt::strong_ordering::equivalent != 0)); + static_assert(!(Qt::strong_ordering::equivalent < 0)); + static_assert( (Qt::strong_ordering::equivalent <= 0)); + static_assert(!(Qt::strong_ordering::equivalent > 0)); + static_assert( (Qt::strong_ordering::equivalent >= 0)); + + static_assert( (0 == Qt::strong_ordering::equivalent)); + static_assert(!(0 != Qt::strong_ordering::equivalent)); + static_assert(!(0 < Qt::strong_ordering::equivalent)); + static_assert( (0 <= Qt::strong_ordering::equivalent)); + static_assert(!(0 > Qt::strong_ordering::equivalent)); + static_assert( (0 >= Qt::strong_ordering::equivalent)); + + + static_assert(!is_eq (Qt::strong_ordering::greater)); + static_assert( is_neq (Qt::strong_ordering::greater)); + static_assert(!is_lt (Qt::strong_ordering::greater)); + static_assert(!is_lteq(Qt::strong_ordering::greater)); + static_assert( is_gt (Qt::strong_ordering::greater)); + static_assert( is_gteq(Qt::strong_ordering::greater)); + + static_assert(!(Qt::strong_ordering::greater == 0)); + static_assert( (Qt::strong_ordering::greater != 0)); + static_assert(!(Qt::strong_ordering::greater < 0)); + static_assert(!(Qt::strong_ordering::greater <= 0)); + static_assert( (Qt::strong_ordering::greater > 0)); + static_assert( (Qt::strong_ordering::greater >= 0)); + + static_assert(!(0 == Qt::strong_ordering::greater)); + static_assert( (0 != Qt::strong_ordering::greater)); + static_assert( (0 < Qt::strong_ordering::greater)); + static_assert( (0 <= Qt::strong_ordering::greater)); + static_assert(!(0 > Qt::strong_ordering::greater)); + static_assert(!(0 >= Qt::strong_ordering::greater)); +} + +void tst_QCompare::threeWayCompareWithLiteralZero() +{ +#ifndef __cpp_lib_three_way_comparison + QSKIP("This test requires C++20 <=> support enabled in the compiler and the stdlib."); +#else + // the result of <=> is _always_ a std::_ordering type: +#define CHECK(O) do { \ + using StdO = typename QtOrderingPrivate::StdOrdering<O>::type; \ + static_assert(std::is_same_v<decltype(0 <=> std::declval<O&>()), StdO>); \ + static_assert(std::is_same_v<decltype(std::declval<O&>() <=> 0), StdO>); \ + } while (false) + + CHECK(Qt::partial_ordering); + CHECK(Qt::weak_ordering); + CHECK(Qt::strong_ordering); + CHECK(QPartialOrdering); + // API symmetry check: + CHECK(std::partial_ordering); + CHECK(std::weak_ordering); + CHECK(std::strong_ordering); + +#undef CHECK + +#define CHECK(O, what, reversed) do { \ + using StdO = typename QtOrderingPrivate::StdOrdering<O>::type; \ + static_assert((O :: what <=> 0) == StdO:: what); \ + static_assert((0 <=> O :: what) == StdO:: reversed); \ + } while (false) + + CHECK(Qt::partial_ordering, unordered, unordered); + CHECK(Qt::partial_ordering, equivalent, equivalent); + CHECK(Qt::partial_ordering, less, greater); + CHECK(Qt::partial_ordering, greater, less); + + CHECK(Qt::weak_ordering, equivalent, equivalent); + CHECK(Qt::weak_ordering, less, greater); + CHECK(Qt::weak_ordering, greater, less); + + CHECK(Qt::strong_ordering, equal, equal); + CHECK(Qt::strong_ordering, less, greater); + CHECK(Qt::strong_ordering, greater, less); + + CHECK(QPartialOrdering, unordered, unordered); + CHECK(QPartialOrdering, equivalent, equivalent); + CHECK(QPartialOrdering, less, greater); + CHECK(QPartialOrdering, greater, less); + + // API symmetry check: + + CHECK(std::partial_ordering, unordered, unordered); + CHECK(std::partial_ordering, equivalent, equivalent); + CHECK(std::partial_ordering, less, greater); + CHECK(std::partial_ordering, greater, less); + + CHECK(std::weak_ordering, equivalent, equivalent); + CHECK(std::weak_ordering, less, greater); + CHECK(std::weak_ordering, greater, less); + + CHECK(std::strong_ordering, equal, equal); + CHECK(std::strong_ordering, less, greater); + CHECK(std::strong_ordering, greater, less); + +#undef CHECK +#endif // __cpp_lib_three_way_comparisons + +} + +void tst_QCompare::conversions() +{ + // Qt::weak_ordering -> Qt::partial_ordering + { + constexpr Qt::partial_ordering less = Qt::weak_ordering::less; + static_assert(less == Qt::partial_ordering::less); + constexpr Qt::partial_ordering equivalent = Qt::weak_ordering::equivalent; + static_assert(equivalent == Qt::partial_ordering::equivalent); + constexpr Qt::partial_ordering greater = Qt::weak_ordering::greater; + static_assert(greater == Qt::partial_ordering::greater); + } + // Qt::strong_ordering -> Qt::partial_ordering + { + constexpr Qt::partial_ordering less = Qt::strong_ordering::less; + static_assert(less == Qt::partial_ordering::less); + constexpr Qt::partial_ordering equal = Qt::strong_ordering::equal; + static_assert(equal == Qt::partial_ordering::equivalent); + constexpr Qt::partial_ordering equivalent = Qt::strong_ordering::equivalent; + static_assert(equivalent == Qt::partial_ordering::equivalent); + constexpr Qt::partial_ordering greater = Qt::strong_ordering::greater; + static_assert(greater == Qt::partial_ordering::greater); + } + // Qt::strong_ordering -> Qt::weak_ordering + { + constexpr Qt::weak_ordering less = Qt::strong_ordering::less; + static_assert(less == Qt::weak_ordering::less); + constexpr Qt::weak_ordering equal = Qt::strong_ordering::equal; + static_assert(equal == Qt::weak_ordering::equivalent); + constexpr Qt::weak_ordering equivalent = Qt::strong_ordering::equivalent; + static_assert(equivalent == Qt::weak_ordering::equivalent); + constexpr Qt::weak_ordering greater = Qt::strong_ordering::greater; + static_assert(greater == Qt::weak_ordering::greater); + } + // Mixed types + { + static_assert(Qt::partial_ordering::less == Qt::strong_ordering::less); + static_assert(Qt::partial_ordering::equivalent != Qt::strong_ordering::less); + static_assert(Qt::partial_ordering::equivalent == Qt::strong_ordering::equal); + static_assert(Qt::partial_ordering::greater == Qt::strong_ordering::greater); + + static_assert(Qt::partial_ordering::less == Qt::weak_ordering::less); + static_assert(Qt::partial_ordering::equivalent == Qt::weak_ordering::equivalent); + static_assert(Qt::partial_ordering::greater == Qt::weak_ordering::greater); + + static_assert(Qt::weak_ordering::less == Qt::strong_ordering::less); + static_assert(Qt::weak_ordering::equivalent != Qt::strong_ordering::greater); + static_assert(Qt::weak_ordering::equivalent == Qt::strong_ordering::equal); + static_assert(Qt::weak_ordering::greater == Qt::strong_ordering::greater); + + static_assert(Qt::weak_ordering::less == Qt::partial_ordering::less); + static_assert(Qt::weak_ordering::equivalent == Qt::partial_ordering::equivalent); + static_assert(Qt::weak_ordering::greater == Qt::partial_ordering::greater); + + static_assert(Qt::strong_ordering::less == Qt::partial_ordering::less); + static_assert(Qt::strong_ordering::equivalent == Qt::partial_ordering::equivalent); + static_assert(Qt::strong_ordering::equal == Qt::partial_ordering::equivalent); + static_assert(Qt::strong_ordering::greater == Qt::partial_ordering::greater); + + static_assert(Qt::strong_ordering::less == Qt::weak_ordering::less); + static_assert(Qt::strong_ordering::equivalent == Qt::weak_ordering::equivalent); + static_assert(Qt::strong_ordering::equal == Qt::weak_ordering::equivalent); + static_assert(Qt::strong_ordering::greater == Qt::weak_ordering::greater); + } +#ifdef __cpp_lib_three_way_comparison + // Qt::partial_ordering <-> std::partial_ordering + { + static_assert(Qt::partial_ordering::less == std::partial_ordering::less); + static_assert(Qt::partial_ordering::less != std::partial_ordering::greater); + static_assert(std::partial_ordering::unordered != Qt::partial_ordering::equivalent); + static_assert(std::partial_ordering::unordered == Qt::partial_ordering::unordered); + + static_assert((Qt::partial_ordering(std::partial_ordering::less) == + std::partial_ordering::less)); + static_assert((Qt::partial_ordering(std::partial_ordering::equivalent) == + std::partial_ordering::equivalent)); + static_assert((Qt::partial_ordering(std::partial_ordering::greater) == + std::partial_ordering::greater)); + static_assert((Qt::partial_ordering(std::partial_ordering::unordered) == + std::partial_ordering::unordered)); + } + // Qt::weak_ordering <-> std::weak_ordering + { + static_assert(Qt::weak_ordering::less == std::weak_ordering::less); + static_assert(Qt::weak_ordering::less != std::weak_ordering::equivalent); + static_assert(std::weak_ordering::greater != Qt::weak_ordering::less); + static_assert(std::weak_ordering::equivalent == Qt::weak_ordering::equivalent); + + static_assert((Qt::weak_ordering(std::weak_ordering::less) == + std::weak_ordering::less)); + static_assert((Qt::weak_ordering(std::weak_ordering::equivalent) == + std::weak_ordering::equivalent)); + static_assert((Qt::weak_ordering(std::weak_ordering::greater) == + std::weak_ordering::greater)); + } + // Qt::strong_ordering <-> std::strong_ordering + { + static_assert(Qt::strong_ordering::less == std::strong_ordering::less); + static_assert(Qt::strong_ordering::less != std::strong_ordering::equivalent); + static_assert(std::strong_ordering::greater != Qt::strong_ordering::less); + static_assert(std::strong_ordering::equivalent == Qt::strong_ordering::equivalent); + + static_assert((Qt::strong_ordering(std::strong_ordering::less) == + std::strong_ordering::less)); + static_assert((Qt::strong_ordering(std::strong_ordering::equivalent) == + std::strong_ordering::equivalent)); + static_assert((Qt::strong_ordering(std::strong_ordering::greater) == + std::strong_ordering::greater)); + } + // Mixed Qt::*_ordering <> std::*_ordering types + { + static_assert(Qt::strong_ordering::less == std::partial_ordering::less); + static_assert(Qt::strong_ordering::less != std::partial_ordering::greater); + static_assert(Qt::strong_ordering::equal == std::weak_ordering::equivalent); + static_assert(Qt::strong_ordering::equivalent != std::weak_ordering::less); + + static_assert(Qt::weak_ordering::less != std::partial_ordering::greater); + static_assert(Qt::weak_ordering::less == std::partial_ordering::less); + static_assert(Qt::weak_ordering::equivalent == std::strong_ordering::equivalent); + static_assert(Qt::weak_ordering::equivalent != std::strong_ordering::less); + + static_assert(Qt::partial_ordering::less != std::weak_ordering::greater); + static_assert(Qt::partial_ordering::less == std::weak_ordering::less); + static_assert(Qt::partial_ordering::equivalent == std::strong_ordering::equivalent); + static_assert(Qt::partial_ordering::equivalent != std::strong_ordering::less); + } +#endif + +} + +void tst_QCompare::is_eq_overloads() +{ +#ifndef __cpp_lib_three_way_comparison + QSKIP("This test requires C++20 three-way-comparison support enabled in the stdlib."); +#else + constexpr auto u = std::partial_ordering::unordered; + constexpr auto l = std::weak_ordering::less; + constexpr auto g = std::strong_ordering::greater; + constexpr auto e = std::weak_ordering::equivalent; + constexpr auto s = std::strong_ordering::equal; + + // This is a compile-time check that unqualified name lookup of + // std::is_eq-like functions isn't ambiguous, so we can recommend it to our + // users for minimizing porting on the way to C++20. + + // The goal is to check each std::ordering and each is_eq function at least + // once, not to test all combinations (we're not the stdlib test suite here). + + QVERIFY(is_eq(s)); + QVERIFY(is_neq(u)); + QVERIFY(is_lt(l)); + QVERIFY(is_gt(g)); + QVERIFY(is_lteq(e)); + QVERIFY(is_gteq(s)); +#endif // __cpp_lib_three_way_comparison +} + +class StringWrapper +{ +public: + explicit StringWrapper() {} + explicit StringWrapper(const QString &val) : m_val(val) {} + QString value() const { return m_val; } + +private: + static Qt::weak_ordering compareHelper(const QString &lhs, const QString &rhs) noexcept + { + const int res = QString::compare(lhs, rhs, Qt::CaseInsensitive); + if (res < 0) + return Qt::weak_ordering::less; + else if (res > 0) + return Qt::weak_ordering::greater; + else + return Qt::weak_ordering::equivalent; + } + + friend bool comparesEqual(const StringWrapper &lhs, const StringWrapper &rhs) noexcept + { return QString::compare(lhs.m_val, rhs.m_val, Qt::CaseInsensitive) == 0; } + friend Qt::weak_ordering + compareThreeWay(const StringWrapper &lhs, const StringWrapper &rhs) noexcept + { return compareHelper(lhs.m_val, rhs.m_val); } + Q_DECLARE_WEAKLY_ORDERED(StringWrapper) + + // these helper functions are intentionally non-noexcept + friend bool comparesEqual(const StringWrapper &lhs, int rhs) + { return comparesEqual(lhs, StringWrapper(QString::number(rhs))); } + friend Qt::weak_ordering compareThreeWay(const StringWrapper &lhs, int rhs) + { return compareHelper(lhs.m_val, QString::number(rhs)); } + Q_DECLARE_WEAKLY_ORDERED(StringWrapper, int) + + QString m_val; +}; + +void tst_QCompare::compareThreeWay() +{ + // test noexcept + + // for custom types + static_assert(noexcept(qCompareThreeWay(std::declval<StringWrapper>(), + std::declval<StringWrapper>()))); + static_assert(!noexcept(qCompareThreeWay(std::declval<StringWrapper>(), + std::declval<int>()))); + static_assert(!noexcept(qCompareThreeWay(std::declval<int>(), + std::declval<StringWrapper>()))); + // for built-in types + static_assert(noexcept(qCompareThreeWay(std::declval<int>(), std::declval<int>()))); + static_assert(noexcept(qCompareThreeWay(std::declval<float>(), std::declval<int>()))); + static_assert(noexcept(qCompareThreeWay(std::declval<double>(), std::declval<float>()))); + static_assert(noexcept(qCompareThreeWay(std::declval<int>(), std::declval<int>()))); + + // enums + enum TestEnum : int { + Smaller, + Bigger + }; + static_assert(noexcept(qCompareThreeWay(std::declval<TestEnum>(), std::declval<TestEnum>()))); + + // pointers + static_assert(noexcept(qCompareThreeWay(std::declval<StringWrapper *>(), + std::declval<StringWrapper *>()))); + static_assert(noexcept(qCompareThreeWay(std::declval<StringWrapper *>(), nullptr))); + + // Test some actual comparison results + + // for custom types + QCOMPARE_EQ(qCompareThreeWay(StringWrapper("ABC"), StringWrapper("abc")), + Qt::weak_ordering::equivalent); + QVERIFY(StringWrapper("ABC") == StringWrapper("abc")); + QCOMPARE_EQ(qCompareThreeWay(StringWrapper("ABC"), StringWrapper("qwe")), + Qt::weak_ordering::less); + QVERIFY(StringWrapper("ABC") != StringWrapper("qwe")); + QCOMPARE_EQ(qCompareThreeWay(StringWrapper("qwe"), StringWrapper("ABC")), + Qt::weak_ordering::greater); + QVERIFY(StringWrapper("qwe") != StringWrapper("ABC")); + QCOMPARE_EQ(qCompareThreeWay(StringWrapper("10"), 10), Qt::weak_ordering::equivalent); + QVERIFY(StringWrapper("10") == 10); + QCOMPARE_EQ(qCompareThreeWay(StringWrapper("10"), 12), Qt::weak_ordering::less); + QVERIFY(StringWrapper("10") != 12); + QCOMPARE_EQ(qCompareThreeWay(StringWrapper("12"), 10), Qt::weak_ordering::greater); + QVERIFY(StringWrapper("12") != 10); + + // reversed compareThreeWay() + auto result = qCompareThreeWay(10, StringWrapper("12")); + QCOMPARE_EQ(result, Qt::weak_ordering::less); + static_assert(std::is_same_v<decltype(result), Qt::weak_ordering>); + QVERIFY(10 != StringWrapper("12")); + result = qCompareThreeWay(12, StringWrapper("10")); + QCOMPARE_EQ(result, Qt::weak_ordering::greater); + static_assert(std::is_same_v<decltype(result), Qt::weak_ordering>); + QVERIFY(12 != StringWrapper("10")); + result = qCompareThreeWay(10, StringWrapper("10")); + QCOMPARE_EQ(result, Qt::weak_ordering::equivalent); + static_assert(std::is_same_v<decltype(result), Qt::weak_ordering>); + QVERIFY(10 == StringWrapper("10")); + + // built-in types + QCOMPARE_EQ(qCompareThreeWay(1, 1.0), Qt::partial_ordering::equivalent); + QCOMPARE_EQ(qCompareThreeWay(1, 2), Qt::strong_ordering::less); + QCOMPARE_EQ(qCompareThreeWay(2.0f, 1.0), Qt::partial_ordering::greater); + + // enums + QCOMPARE_EQ(qCompareThreeWay(Smaller, Bigger), Qt::strong_ordering::less); + + // pointers + std::array<int, 2> arr{1, 0}; + QCOMPARE_EQ(qCompareThreeWay(&arr[1], &arr[0]), Qt::strong_ordering::greater); + QCOMPARE_EQ(qCompareThreeWay(arr.data(), &arr[0]), Qt::strong_ordering::equivalent); +} + QTEST_MAIN(tst_QCompare) #include "tst_qcompare.moc" diff --git a/tests/auto/corelib/global/qcomparehelpers/CMakeLists.txt b/tests/auto/corelib/global/qcomparehelpers/CMakeLists.txt new file mode 100644 index 0000000000..31d8bff0a5 --- /dev/null +++ b/tests/auto/corelib/global/qcomparehelpers/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcomparehelpers LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qcomparehelpers + SOURCES + tst_qcomparehelpers.h tst_qcomparehelpers.cpp tst_qcomparehelpers1.cpp + wrappertypes.h + LIBRARIES + Qt::TestPrivate +) + +# CMake recognizes CXX_STANDARD=23 only starting from version 3.20 +# macOS has some issues with concepts, see QTBUG-117765 +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20" AND NOT MACOS AND NOT VXWORKS AND NOT (LINUX AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "aarch64")) + qt_internal_add_test(tst_qcomparehelpers_cpp23 + SOURCES + tst_qcomparehelpers.h tst_qcomparehelpers.cpp tst_qcomparehelpers1.cpp + wrappertypes.h + DEFINES + tst_QCompareHelpers=tst_QCompareHelpersCpp23 + LIBRARIES + Qt::TestPrivate + ) + + # Try to build this test in C++23 mode to test std::float16_t support. + # Use CXX_STANDARD_REQUIRED OFF, so that we just fall back to C++17 if the + # compiler does not support C++23. + set_target_properties(tst_qcomparehelpers_cpp23 + PROPERTIES + CXX_STANDARD 23 + CXX_STANDARD_REQUIRED OFF + ) +endif() diff --git a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp new file mode 100644 index 0000000000..f140c23ed0 --- /dev/null +++ b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp @@ -0,0 +1,600 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "tst_qcomparehelpers.h" +#include "wrappertypes.h" + +#if defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>) +#include <stdfloat> +#endif + +/* + NOTE: Do not add any other test cases to this cpp file! + minGW already complains about a too large tst_qcomparehelpers.cpp.obj + object file. + + Create a new cpp file and add new tests there. +*/ + +template<typename LeftType, typename RightType, typename OrderingType> +void tst_QCompareHelpers::compareImpl() +{ + QFETCH(LeftType, lhs); + QFETCH(RightType, rhs); + QFETCH(OrderingType, expectedOrdering); + + QT_TEST_ALL_COMPARISON_OPS(lhs, rhs, expectedOrdering); +#ifdef __cpp_lib_three_way_comparison + // Also check std types. + QT_TEST_ALL_COMPARISON_OPS(lhs, rhs, QtOrderingPrivate::to_std(expectedOrdering)); +#endif // __cpp_lib_three_way_comparison +} + +template<typename LeftType, typename RightType> +void tst_QCompareHelpers::compareIntData() +{ + QTest::addColumn<LeftType>("lhs"); + QTest::addColumn<RightType>("rhs"); + QTest::addColumn<Qt::strong_ordering>("expectedOrdering"); + + auto createRow = [](auto lhs, auto rhs, Qt::strong_ordering ordering) { + QTest::addRow("%d vs %d", lhs, rhs) << LeftType(lhs) << RightType(rhs) << ordering; + }; + + createRow(0, 0, Qt::strong_ordering::equivalent); + createRow(-1, 0, Qt::strong_ordering::less); + createRow(1, 0, Qt::strong_ordering::greater); + constexpr int max = std::numeric_limits<int>::max(); + constexpr int min = std::numeric_limits<int>::min(); + createRow(max, max, Qt::strong_ordering::equivalent); + createRow(min, min, Qt::strong_ordering::equivalent); + createRow(max, min, Qt::strong_ordering::greater); + createRow(min, max, Qt::strong_ordering::less); +} + +template<typename LeftType, typename RightType> +void tst_QCompareHelpers::compareFloatData() +{ + QTest::addColumn<LeftType>("lhs"); + QTest::addColumn<RightType>("rhs"); + QTest::addColumn<Qt::partial_ordering>("expectedOrdering"); + + auto createRow = [](auto lhs, auto rhs, Qt::partial_ordering ordering) { + QTest::addRow("%f vs %f", lhs, rhs) << LeftType(lhs) << RightType(rhs) << ordering; + }; + + createRow(0.0, 0.0, Qt::partial_ordering::equivalent); + createRow(-0.000001, 0.0, Qt::partial_ordering::less); + createRow(0.000001, 0.0, Qt::partial_ordering::greater); + + const double nan = qQNaN(); + createRow(nan, 0.0, Qt::partial_ordering::unordered); + createRow(0.0, nan, Qt::partial_ordering::unordered); + createRow(nan, nan, Qt::partial_ordering::unordered); + + const double inf = qInf(); + createRow(inf, 0.0, Qt::partial_ordering::greater); + createRow(0.0, inf, Qt::partial_ordering::less); + createRow(-inf, 0.0, Qt::partial_ordering::less); + createRow(0.0, -inf, Qt::partial_ordering::greater); + createRow(inf, inf, Qt::partial_ordering::equivalent); + createRow(-inf, -inf, Qt::partial_ordering::equivalent); + createRow(-inf, inf, Qt::partial_ordering::less); + createRow(inf, -inf, Qt::partial_ordering::greater); + + createRow(nan, inf, Qt::partial_ordering::unordered); + createRow(inf, nan, Qt::partial_ordering::unordered); + createRow(nan, -inf, Qt::partial_ordering::unordered); + createRow(-inf, nan, Qt::partial_ordering::unordered); +} + +template<typename LeftType, typename RightType> +void tst_QCompareHelpers::compareStringData() +{ + QTest::addColumn<LeftType>("lhs"); + QTest::addColumn<RightType>("rhs"); + QTest::addColumn<Qt::weak_ordering>("expectedOrdering"); + + auto createRow = [](auto lhs, auto rhs, Qt::weak_ordering ordering) { + QTest::addRow("'%s' vs '%s'", lhs, rhs) << LeftType(lhs) << RightType(rhs) << ordering; + }; + + createRow("", "", Qt::weak_ordering::equivalent); + createRow("Ab", "abc", Qt::weak_ordering::less); + createRow("aBc", "AB", Qt::weak_ordering::greater); + createRow("ab", "AB", Qt::weak_ordering::equivalent); + createRow("ABC", "abc", Qt::weak_ordering::equivalent); +} + +void tst_QCompareHelpers::comparisonCompiles() +{ + QTestPrivate::testAllComparisonOperatorsCompile<IntWrapper>(); + if (QTest::currentTestFailed()) + return; + + QTestPrivate::testAllComparisonOperatorsCompile<IntWrapper, int>(); + if (QTest::currentTestFailed()) + return; + + QTestPrivate::testAllComparisonOperatorsCompile<DoubleWrapper>(); + if (QTest::currentTestFailed()) + return; + + QTestPrivate::testAllComparisonOperatorsCompile<DoubleWrapper, double>(); + if (QTest::currentTestFailed()) + return; + + QTestPrivate::testAllComparisonOperatorsCompile<DoubleWrapper, IntWrapper>(); + if (QTest::currentTestFailed()) + return; + + QTestPrivate::testAllComparisonOperatorsCompile<StringWrapper<QString>>(); + if (QTest::currentTestFailed()) + return; + + QTestPrivate::testAllComparisonOperatorsCompile<StringWrapper<QString>, QAnyStringView>(); + if (QTest::currentTestFailed()) + return; +} + +void tst_QCompareHelpers::compare_IntWrapper_data() +{ + compareIntData<IntWrapper, IntWrapper>(); +} + +void tst_QCompareHelpers::compare_IntWrapper() +{ + compareImpl<IntWrapper, IntWrapper, Qt::strong_ordering>(); +} + +void tst_QCompareHelpers::compare_IntWrapper_int_data() +{ + compareIntData<IntWrapper, int>(); +} + +void tst_QCompareHelpers::compare_IntWrapper_int() +{ + compareImpl<IntWrapper, int, Qt::strong_ordering>(); +} + +void tst_QCompareHelpers::compare_DoubleWrapper_data() +{ + compareFloatData<DoubleWrapper, DoubleWrapper>(); +} + +void tst_QCompareHelpers::compare_DoubleWrapper() +{ + compareImpl<DoubleWrapper, DoubleWrapper, Qt::partial_ordering>(); +} + +void tst_QCompareHelpers::compare_DoubleWrapper_double_data() +{ + compareFloatData<DoubleWrapper, double>(); +} + +void tst_QCompareHelpers::compare_DoubleWrapper_double() +{ + compareImpl<DoubleWrapper, double, Qt::partial_ordering>(); +} + +void tst_QCompareHelpers::compare_IntWrapper_DoubleWrapper_data() +{ + QTest::addColumn<IntWrapper>("lhs"); + QTest::addColumn<DoubleWrapper>("rhs"); + QTest::addColumn<Qt::partial_ordering>("expectedOrdering"); + + auto createRow = [](auto lhs, auto rhs, Qt::partial_ordering ordering) { + QTest::addRow("%d vs %f", lhs, rhs) << IntWrapper(lhs) << DoubleWrapper(rhs) << ordering; + }; + + createRow(0, 0.0, Qt::partial_ordering::equivalent); + createRow(-1, 0.0, Qt::partial_ordering::less); + createRow(1, 0.0, Qt::partial_ordering::greater); + createRow(0, -0.000001, Qt::partial_ordering::greater); + createRow(0, 0.000001, Qt::partial_ordering::less); + + constexpr int max = std::numeric_limits<int>::max(); + constexpr int min = std::numeric_limits<int>::min(); + const double nan = qQNaN(); + createRow(0, nan, Qt::partial_ordering::unordered); + createRow(max, nan, Qt::partial_ordering::unordered); + createRow(min, nan, Qt::partial_ordering::unordered); + + const double inf = qInf(); + createRow(0, inf, Qt::partial_ordering::less); + createRow(0, -inf, Qt::partial_ordering::greater); + createRow(max, inf, Qt::partial_ordering::less); + createRow(max, -inf, Qt::partial_ordering::greater); + createRow(min, inf, Qt::partial_ordering::less); + createRow(min, -inf, Qt::partial_ordering::greater); +} + +void tst_QCompareHelpers::compare_IntWrapper_DoubleWrapper() +{ + compareImpl<IntWrapper, DoubleWrapper, Qt::partial_ordering>(); +} + +void tst_QCompareHelpers::compare_StringWrapper_data() +{ + compareStringData<StringWrapper<QString>, StringWrapper<QString>>(); +} + +void tst_QCompareHelpers::compare_StringWrapper() +{ + compareImpl<StringWrapper<QString>, StringWrapper<QString>, Qt::weak_ordering>(); +} + +void tst_QCompareHelpers::compare_StringWrapper_AnyStringView_data() +{ + compareStringData<StringWrapper<QString>, QAnyStringView>(); +} + +void tst_QCompareHelpers::compare_StringWrapper_AnyStringView() +{ + compareImpl<StringWrapper<QString>, QAnyStringView, Qt::weak_ordering>(); +} + +#define DECLARE_TYPE(Name, Type, Attrs, RetType, Constexpr, Suffix) \ +class Dummy ## Name \ +{ \ +public: \ + Constexpr Dummy ## Name () {} \ +\ +private: \ + friend Attrs Constexpr bool \ + comparesEqual(const Dummy ## Name &lhs, const Dummy ## Name &rhs) noexcept; \ + friend Attrs Constexpr RetType \ + compareThreeWay(const Dummy ## Name &lhs, const Dummy ## Name &rhs) noexcept; \ + friend Attrs Constexpr bool \ + comparesEqual(const Dummy ## Name &lhs, int rhs) noexcept; \ + friend Attrs Constexpr RetType \ + compareThreeWay(const Dummy ## Name &lhs, int rhs) noexcept; \ + Q_DECLARE_ ## Type ##_ORDERED ## Suffix (Dummy ## Name) \ + Q_DECLARE_ ## Type ##_ORDERED ## Suffix (Dummy ## Name, int) \ +}; \ +\ +Attrs Constexpr bool comparesEqual(const Dummy ## Name &lhs, const Dummy ## Name &rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return true; } \ +Attrs Constexpr RetType \ +compareThreeWay(const Dummy ## Name &lhs, const Dummy ## Name &rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return RetType::equivalent; } \ +Attrs Constexpr bool comparesEqual(const Dummy ## Name &lhs, int rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return true; } \ +Attrs Constexpr RetType compareThreeWay(const Dummy ## Name &lhs, int rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return RetType::equivalent; } + +DECLARE_TYPE(PartialConstAttr, PARTIALLY, Q_DECL_PURE_FUNCTION, Qt::partial_ordering, constexpr, + _LITERAL_TYPE) +DECLARE_TYPE(PartialConst, PARTIALLY, /* no attrs */, Qt::partial_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(PartialAttr, PARTIALLY, Q_DECL_CONST_FUNCTION, Qt::partial_ordering, , ) +DECLARE_TYPE(Partial, PARTIALLY, /* no attrs */, Qt::partial_ordering, , ) + +DECLARE_TYPE(WeakConstAttr, WEAKLY, Q_DECL_PURE_FUNCTION, Qt::weak_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(WeakConst, WEAKLY, /* no attrs */, Qt::weak_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(WeakAttr, WEAKLY, Q_DECL_CONST_FUNCTION, Qt::weak_ordering, , ) +DECLARE_TYPE(Weak, WEAKLY, /* no attrs */, Qt::weak_ordering, , ) + +DECLARE_TYPE(StrongConstAttr, STRONGLY, Q_DECL_PURE_FUNCTION, Qt::strong_ordering, constexpr, + _LITERAL_TYPE) +DECLARE_TYPE(StrongConst, STRONGLY, /* no attrs */, Qt::strong_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(StrongAttr, STRONGLY, Q_DECL_CONST_FUNCTION, Qt::strong_ordering, , ) +DECLARE_TYPE(Strong, STRONGLY, /* no attrs */, Qt::strong_ordering, , ) + +#define DECLARE_EQUALITY_COMPARABLE(Name, Attrs, Constexpr, Suffix) \ +class Dummy ## Name \ +{ \ +public: \ + Constexpr Dummy ## Name (int) {} \ +\ +private: \ + friend Attrs Constexpr bool \ + comparesEqual(const Dummy ## Name &lhs, const Dummy ## Name &rhs) noexcept; \ + friend Attrs Constexpr bool comparesEqual(const Dummy ## Name &lhs, int rhs) noexcept; \ + Q_DECLARE_EQUALITY_COMPARABLE ## Suffix (Dummy ## Name) \ + Q_DECLARE_EQUALITY_COMPARABLE ## Suffix (Dummy ## Name, int) \ +}; \ +\ +Attrs Constexpr bool comparesEqual(const Dummy ## Name &lhs, const Dummy ## Name &rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return true; } \ +Attrs Constexpr bool comparesEqual(const Dummy ## Name &lhs, int rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return true; } \ + +DECLARE_EQUALITY_COMPARABLE(ConstAttr, Q_DECL_PURE_FUNCTION, constexpr, _LITERAL_TYPE) +DECLARE_EQUALITY_COMPARABLE(Const, /* no attrs */, constexpr, _LITERAL_TYPE) +DECLARE_EQUALITY_COMPARABLE(Attr, Q_DECL_CONST_FUNCTION, , ) +DECLARE_EQUALITY_COMPARABLE(None, /* no attrs */, , ) + +void tst_QCompareHelpers::generatedClasses() +{ +#define COMPARE(ClassName) \ + do { \ + QTestPrivate::testAllComparisonOperatorsCompile<ClassName>(); \ + QTestPrivate::testAllComparisonOperatorsCompile<ClassName, int>(); \ + } while (0) + + COMPARE(DummyPartialConstAttr); + COMPARE(DummyPartialConst); + COMPARE(DummyPartialAttr); + COMPARE(DummyPartial); + + COMPARE(DummyWeakConstAttr); + COMPARE(DummyWeakConst); + COMPARE(DummyWeakAttr); + COMPARE(DummyWeak); + + COMPARE(DummyStrongConstAttr); + COMPARE(DummyStrongConst); + COMPARE(DummyStrongAttr); + COMPARE(DummyStrong); +#undef COMPARE + + QTestPrivate::testEqualityOperatorsCompile<DummyConstAttr>(); + QTestPrivate::testEqualityOperatorsCompile<DummyConstAttr, int>(); + + QTestPrivate::testEqualityOperatorsCompile<DummyConst>(); + QTestPrivate::testEqualityOperatorsCompile<DummyConst, int>(); + + QTestPrivate::testEqualityOperatorsCompile<DummyAttr>(); + QTestPrivate::testEqualityOperatorsCompile<DummyAttr, int>(); + + QTestPrivate::testEqualityOperatorsCompile<DummyNone>(); + QTestPrivate::testEqualityOperatorsCompile<DummyNone, int>(); +} + +template <typename LeftType, typename RightType, + Qt::if_integral<LeftType> = true, + Qt::if_integral<RightType> = true> +void testOrderForTypes() +{ + LeftType l0{0}; + LeftType l1{1}; + RightType r0{0}; + RightType r1{1}; + QCOMPARE_EQ(Qt::compareThreeWay(l0, r1), Qt::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l1, r0), Qt::strong_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(l1, r1), Qt::strong_ordering::equivalent); + // also swap types + QCOMPARE_EQ(Qt::compareThreeWay(r1, l0), Qt::strong_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(r0, l1), Qt::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(r1, l1), Qt::strong_ordering::equivalent); + +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(Qt::compareThreeWay(l0, r1), std::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l1, r0), std::strong_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(l1, r1), std::strong_ordering::equivalent); + + QCOMPARE_EQ(Qt::compareThreeWay(r1, l0), std::strong_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(r0, l1), std::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(r1, l1), std::strong_ordering::equivalent); +#endif // __cpp_lib_three_way_comparison + + if constexpr (std::is_signed_v<LeftType>) { + LeftType lm1{-1}; + QCOMPARE_EQ(Qt::compareThreeWay(lm1, r1), Qt::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(r1, lm1), Qt::strong_ordering::greater); +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(Qt::compareThreeWay(lm1, r1), std::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(r1, lm1), std::strong_ordering::greater); +#endif // __cpp_lib_three_way_comparison + } + if constexpr (std::is_signed_v<RightType>) { + RightType rm1{-1}; + QCOMPARE_EQ(Qt::compareThreeWay(rm1, l1), Qt::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l1, rm1), Qt::strong_ordering::greater); +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(Qt::compareThreeWay(rm1, l1), std::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l1, rm1), std::strong_ordering::greater); +#endif // __cpp_lib_three_way_comparison + } +} + +template <typename LeftType, typename RightType, + Qt::if_floating_point<LeftType> = true, + Qt::if_floating_point<RightType> = true> +void testOrderForTypes() +{ + constexpr auto lNeg = LeftType(-1); + constexpr auto lPos = LeftType( 1); + + constexpr auto rNeg = RightType(-1); + constexpr auto rPos = RightType( 1); + + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rPos), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(lPos, rNeg), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(rNeg, lPos), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(rPos, lNeg), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rNeg), Qt::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(rNeg, lNeg), Qt::partial_ordering::equivalent); + + LeftType lNaN{std::numeric_limits<LeftType>::quiet_NaN()}; + LeftType lInf{std::numeric_limits<LeftType>::infinity()}; + + RightType rNaN{std::numeric_limits<RightType>::quiet_NaN()}; + RightType rInf{std::numeric_limits<RightType>::infinity()}; + + QCOMPARE_EQ(Qt::compareThreeWay(lNaN, rPos), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNeg, lNaN), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rNaN), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, lPos), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, lNaN), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(lNaN, rNaN), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(lNaN, rInf), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, -lInf), Qt::partial_ordering::unordered); + + QCOMPARE_EQ(Qt::compareThreeWay(lInf, rPos), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(rPos, lInf), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(rInf, lNeg), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rInf), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(lInf, -rInf), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(-lInf, rInf), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(-rInf, lInf), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(rInf, -lInf), Qt::partial_ordering::greater); + +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rPos), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(lPos, rNeg), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(rNeg, lPos), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(rPos, lNeg), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rNeg), std::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(rNeg, lNeg), std::partial_ordering::equivalent); + + QCOMPARE_EQ(Qt::compareThreeWay(lNaN, rPos), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNeg, lNaN), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rNaN), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, lPos), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, lNaN), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(lNaN, rNaN), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(lNaN, rInf), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, -lInf), std::partial_ordering::unordered); + + QCOMPARE_EQ(Qt::compareThreeWay(lInf, rPos), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(rPos, lInf), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(rInf, lNeg), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(lNeg, rInf), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(lInf, -rInf), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(-lInf, rInf), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(-rInf, lInf), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(rInf, -lInf), std::partial_ordering::greater); +#endif // __cpp_lib_three_way_comparison +} + +template <typename IntType, typename FloatType, + Qt::if_integral<IntType> = true, + Qt::if_floating_point<FloatType> = true> +void testOrderForTypes() +{ + IntType l0{0}; + IntType l1{1}; + + constexpr FloatType r0{0}; + constexpr FloatType r1{1}; + FloatType rNaN{std::numeric_limits<FloatType>::quiet_NaN()}; + + QCOMPARE_EQ(Qt::compareThreeWay(l0, r1), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l1, r0), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(r1, l0), Qt::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(r0, l1), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l0, r0), Qt::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(r0, l0), Qt::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(l0, rNaN), Qt::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, l1), Qt::partial_ordering::unordered); +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(Qt::compareThreeWay(l0, r1), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l1, r0), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(r1, l0), std::partial_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(r0, l1), std::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(l0, r0), std::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(r0, l0), std::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(l0, rNaN), std::partial_ordering::unordered); + QCOMPARE_EQ(Qt::compareThreeWay(rNaN, l1), std::partial_ordering::unordered); +#endif // __cpp_lib_three_way_comparison +} + +enum class TestEnum : quint8 { + Smaller, + Bigger +}; + +void tst_QCompareHelpers::builtinOrder() +{ +#define TEST_BUILTIN(Left, Right) \ + testOrderForTypes<Left, Right>(); \ + if (QTest::currentTestFailed()) { \ + qDebug("Failed Qt::compareThreeWay() test for builtin types " #Left " and " #Right); \ + return; \ + } + + // some combinations + TEST_BUILTIN(char, char) +#if CHAR_MIN < 0 + TEST_BUILTIN(char, short) + TEST_BUILTIN(qint8, char) +#else + TEST_BUILTIN(char, ushort) + TEST_BUILTIN(quint8, char) +#endif + TEST_BUILTIN(qint8, qint8) + TEST_BUILTIN(qint8, int) + TEST_BUILTIN(ulong, quint8) + TEST_BUILTIN(ushort, uchar) + TEST_BUILTIN(int, int) + TEST_BUILTIN(uint, ulong) + TEST_BUILTIN(long, int) + TEST_BUILTIN(uint, quint64) + TEST_BUILTIN(qint64, short) + TEST_BUILTIN(wchar_t, wchar_t) + TEST_BUILTIN(uint, char16_t) + TEST_BUILTIN(char32_t, char32_t) + TEST_BUILTIN(char32_t, ushort) +#ifdef __cpp_char8_t + TEST_BUILTIN(char8_t, char8_t) + TEST_BUILTIN(char8_t, ushort) + TEST_BUILTIN(char8_t, uint) + TEST_BUILTIN(char8_t, quint64) +#endif // __cpp_char8_t +#ifdef QT_SUPPORTS_INT128 + TEST_BUILTIN(qint128, qint128) + TEST_BUILTIN(quint128, quint128) + TEST_BUILTIN(qint128, int) + TEST_BUILTIN(ushort, quint128) +#endif + TEST_BUILTIN(float, double) + TEST_BUILTIN(double, float) + TEST_BUILTIN(quint64, float) + TEST_BUILTIN(qint64, double) +#ifdef __STDCPP_FLOAT16_T__ + TEST_BUILTIN(std::float16_t, std::float16_t) + TEST_BUILTIN(std::float16_t, double) + TEST_BUILTIN(qint64, std::float16_t) + TEST_BUILTIN(uint, std::float16_t) +#endif + TEST_BUILTIN(long double, long double) + TEST_BUILTIN(float, long double) + TEST_BUILTIN(double, long double) + TEST_BUILTIN(quint64, long double) + TEST_BUILTIN(ushort, long double) + +#if QFLOAT16_IS_NATIVE + { + // Cannot use TEST_BUILTIN here, because std::numeric_limits are not defined + // for QtPrivate::NativeFloat16Type. + constexpr auto smaller = QtPrivate::NativeFloat16Type(1); + constexpr auto bigger = QtPrivate::NativeFloat16Type(2); + // native vs native + QCOMPARE_EQ(Qt::compareThreeWay(smaller, smaller), Qt::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(smaller, bigger), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(bigger, smaller), Qt::partial_ordering::greater); + // native vs float + QCOMPARE_EQ(Qt::compareThreeWay(smaller, 1.0f), Qt::partial_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(1.0f, bigger), Qt::partial_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(bigger, 1.0f), Qt::partial_ordering::greater); + const auto floatNaN = std::numeric_limits<float>::quiet_NaN(); + QCOMPARE_EQ(Qt::compareThreeWay(bigger, floatNaN), Qt::partial_ordering::unordered); + } +#endif + + QCOMPARE_EQ(Qt::compareThreeWay(TestEnum::Smaller, TestEnum::Bigger), + Qt::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(TestEnum::Bigger, TestEnum::Smaller), + Qt::strong_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(TestEnum::Smaller, TestEnum::Smaller), + Qt::strong_ordering::equivalent); + + std::array<int, 2> arr{1, 0}; + QCOMPARE_EQ(Qt::compareThreeWay(&arr[0], &arr[1]), Qt::strong_ordering::less); + QCOMPARE_EQ(Qt::compareThreeWay(arr.data(), &arr[0]), Qt::strong_ordering::equivalent); + + class Base {}; + class Derived : public Base {}; + + auto b = std::make_unique<Base>(); + auto d = std::make_unique<Derived>(); + QCOMPARE_NE(Qt::compareThreeWay(b.get(), d.get()), Qt::strong_ordering::equivalent); + QCOMPARE_EQ(Qt::compareThreeWay(b.get(), nullptr), Qt::strong_ordering::greater); + QCOMPARE_EQ(Qt::compareThreeWay(nullptr, d.get()), Qt::strong_ordering::less); + +#undef TEST_BUILTIN +} + +QTEST_MAIN(tst_QCompareHelpers) +#include "tst_qcomparehelpers.moc" diff --git a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.h b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.h new file mode 100644 index 0000000000..16398b0978 --- /dev/null +++ b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.h @@ -0,0 +1,63 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef TST_QCOMPAREHELPERS_H +#define TST_QCOMPAREHELPERS_H + +#include <QtCore/qcompare.h> + +#include <QtTest/qtest.h> +#include <QtTest/private/qcomparisontesthelper_p.h> + +class tst_QCompareHelpers : public QObject +{ + Q_OBJECT + +private: + template <typename LeftType, typename RightType, typename OrderingType> + void compareImpl(); + + template <typename LeftType, typename RightType> + void compareIntData(); + + template <typename LeftType, typename RightType> + void compareFloatData(); + + template <typename LeftType, typename RightType> + void compareStringData(); + +private Q_SLOTS: + // tst_qcomparehelpers.cpp + void comparisonCompiles(); + + void compare_IntWrapper_data(); + void compare_IntWrapper(); + + void compare_IntWrapper_int_data(); + void compare_IntWrapper_int(); + + void compare_DoubleWrapper_data(); + void compare_DoubleWrapper(); + + void compare_DoubleWrapper_double_data(); + void compare_DoubleWrapper_double(); + + void compare_IntWrapper_DoubleWrapper_data(); + void compare_IntWrapper_DoubleWrapper(); + + void compare_StringWrapper_data(); + void compare_StringWrapper(); + + void compare_StringWrapper_AnyStringView_data(); + void compare_StringWrapper_AnyStringView(); + + void generatedClasses(); + + void builtinOrder(); + + // Add new test cases to tst_qcomparehelpers1.cpp, because minGW already + // complains about a too large tst_qcomparehelpers.cpp.obj object file + void compareWithAttributes(); +}; + +#endif // TST_QCOMPAREHELPERS_H diff --git a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers1.cpp b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers1.cpp new file mode 100644 index 0000000000..a3b8200a63 --- /dev/null +++ b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers1.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "tst_qcomparehelpers.h" + +#define DECLARE_TYPE(Name, Type, RetType, Constexpr, Suffix) \ +class Deprecated ## Name \ +{ \ +public: \ + Constexpr Deprecated ## Name () {} \ +\ +private: \ + friend Constexpr bool \ + comparesEqual(const Deprecated ## Name &lhs, int rhs) noexcept; \ + friend Constexpr RetType \ + compareThreeWay(const Deprecated ## Name &lhs, int rhs) noexcept; \ + Q_DECLARE_ ## Type ## _ORDERED ## Suffix (Deprecated ## Name, int, \ + Q_DECL_DEPRECATED_X("This op is deprecated")) \ +}; \ +\ +Constexpr bool comparesEqual(const Deprecated ## Name &lhs, int rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return true; } \ +Constexpr RetType compareThreeWay(const Deprecated ## Name &lhs, int rhs) noexcept \ +{ Q_UNUSED(lhs); Q_UNUSED(rhs); return RetType::equivalent; } + +DECLARE_TYPE(PartialConst, PARTIALLY, Qt::partial_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(Partial, PARTIALLY, Qt::partial_ordering, , ) +DECLARE_TYPE(WeakConst, WEAKLY, Qt::weak_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(Weak, WEAKLY, Qt::weak_ordering, , ) +DECLARE_TYPE(StrongConst, STRONGLY, Qt::strong_ordering, constexpr, _LITERAL_TYPE) +DECLARE_TYPE(Strong, STRONGLY, Qt::strong_ordering, , ) + +#undef DECLARE_TYPE + +void tst_QCompareHelpers::compareWithAttributes() +{ + // All these comparisons would trigger deprecation warnings. +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED + +#define COMPARE(ClassName) \ + do { \ + ClassName c; \ + QCOMPARE_EQ(c, 0); \ + QCOMPARE_LE(c, 0); \ + QCOMPARE_GE(0, c); \ + } while (false) + + COMPARE(DeprecatedPartialConst); + COMPARE(DeprecatedPartial); + COMPARE(DeprecatedWeakConst); + COMPARE(DeprecatedWeak); + COMPARE(DeprecatedStrongConst); + COMPARE(DeprecatedStrong); + +#undef COMPARE + +QT_WARNING_POP +} diff --git a/tests/auto/corelib/global/qcomparehelpers/wrappertypes.h b/tests/auto/corelib/global/qcomparehelpers/wrappertypes.h new file mode 100644 index 0000000000..1dd221a8b0 --- /dev/null +++ b/tests/auto/corelib/global/qcomparehelpers/wrappertypes.h @@ -0,0 +1,116 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef TST_QCOMPAREHELPERS_WRAPPERTYPES_H +#define TST_QCOMPAREHELPERS_WRAPPERTYPES_H + +#include <QtCore/qanystringview.h> +#include <QtCore/qcompare.h> + +class IntWrapper +{ +public: + // implicit constructor and operator int() to simulate the case that + // triggers a bug on MSVC < 19.36. + IntWrapper(int val) : m_val(val) {} + operator int() const noexcept { return m_val; } + + int value() const { return m_val; } + +private: + friend bool comparesEqual(const IntWrapper &lhs, const IntWrapper &rhs) noexcept + { return lhs.m_val == rhs.m_val; } + friend Qt::strong_ordering + compareThreeWay(const IntWrapper &lhs, const IntWrapper &rhs) noexcept + { + return Qt::compareThreeWay(lhs.m_val, rhs.m_val); + } + friend bool comparesEqual(const IntWrapper &lhs, int rhs) noexcept + { return lhs.m_val == rhs; } + friend Qt::strong_ordering compareThreeWay(const IntWrapper &lhs, int rhs) noexcept + { return compareThreeWay(lhs, IntWrapper(rhs)); } + + Q_DECLARE_STRONGLY_ORDERED(IntWrapper) + Q_DECLARE_STRONGLY_ORDERED(IntWrapper, int) + + int m_val = 0; +}; + +class DoubleWrapper +{ +public: + explicit DoubleWrapper(double val) : m_val(val) {} + double value() const { return m_val; } + +private: + friend bool comparesEqual(const DoubleWrapper &lhs, const DoubleWrapper &rhs) noexcept + { return lhs.m_val == rhs.m_val; } + friend Qt::partial_ordering + compareThreeWay(const DoubleWrapper &lhs, const DoubleWrapper &rhs) noexcept + { + return Qt::compareThreeWay(lhs.m_val, rhs.m_val); + } + friend bool comparesEqual(const DoubleWrapper &lhs, const IntWrapper &rhs) noexcept + { return comparesEqual(lhs, DoubleWrapper(rhs.value())); } + friend Qt::partial_ordering + compareThreeWay(const DoubleWrapper &lhs, const IntWrapper &rhs) noexcept + { return compareThreeWay(lhs, DoubleWrapper(rhs.value())); } + friend bool comparesEqual(const DoubleWrapper &lhs, double rhs) noexcept + { return lhs.m_val == rhs; } + friend Qt::partial_ordering compareThreeWay(const DoubleWrapper &lhs, double rhs) noexcept + { + return Qt::compareThreeWay(lhs.m_val, rhs); + } + + Q_DECLARE_PARTIALLY_ORDERED(DoubleWrapper) + Q_DECLARE_PARTIALLY_ORDERED(DoubleWrapper, IntWrapper) + Q_DECLARE_PARTIALLY_ORDERED(DoubleWrapper, double) + + double m_val = 0.0; +}; + +template <typename String> +class StringWrapper +{ +public: + explicit StringWrapper(String val) : m_val(val) {} + String value() const { return m_val; } + +private: + static bool equalsHelper(QAnyStringView lhs, QAnyStringView rhs) noexcept + { return QAnyStringView::compare(lhs, rhs, Qt::CaseInsensitive) == 0; } + + static Qt::weak_ordering compareHelper(QAnyStringView lhs, QAnyStringView rhs) noexcept + { + const int res = QAnyStringView::compare(lhs, rhs, Qt::CaseInsensitive); + if (res < 0) + return Qt::weak_ordering::less; + else if (res > 0) + return Qt::weak_ordering::greater; + else + return Qt::weak_ordering::equivalent; + } + + // Some of the helper functions are intentionally NOT marked as noexcept + // to test the conditional noexcept in the macros. + template <typename T> + friend bool comparesEqual(const StringWrapper<T> &lhs, const StringWrapper<T> &rhs) noexcept + { return StringWrapper<T>::equalsHelper(lhs.m_val, rhs.m_val); } + template <typename T> + friend Qt::weak_ordering + compareThreeWay(const StringWrapper<T> &lhs, const StringWrapper<T> &rhs) noexcept + { return StringWrapper<T>::compareHelper(lhs.m_val, rhs.m_val); } + template <typename T> + friend bool comparesEqual(const StringWrapper<T> &lhs, QAnyStringView rhs) + { return StringWrapper<T>::equalsHelper(lhs.m_val, rhs); } + template <typename T> + friend Qt::weak_ordering compareThreeWay(const StringWrapper<T> &lhs, QAnyStringView rhs) + { return StringWrapper<T>::compareHelper(lhs.m_val, rhs); } + + Q_DECLARE_WEAKLY_ORDERED(StringWrapper) + Q_DECLARE_WEAKLY_ORDERED(StringWrapper, QAnyStringView) + + String m_val; +}; + +#endif // TST_QCOMPAREHELPERS_WRAPPERTYPES_H diff --git a/tests/auto/corelib/global/qflags/CMakeLists.txt b/tests/auto/corelib/global/qflags/CMakeLists.txt index 998834d619..8b01ea774f 100644 --- a/tests/auto/corelib/global/qflags/CMakeLists.txt +++ b/tests/auto/corelib/global/qflags/CMakeLists.txt @@ -1,13 +1,24 @@ -# Generated from qflags.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qflags Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qflags LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qflags SOURCES tst_qflags.cpp ) -## Scopes: -##################################################################### +qt_internal_add_test(tst_qflags_non_typesafe + SOURCES + tst_qflags.cpp + DEFINES + QFLAGS_TEST_NO_TYPESAFE_FLAGS +) diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp index 3179cfc9d2..d226e8d6b4 100644 --- a/tests/auto/corelib/global/qflags/tst_qflags.cpp +++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp @@ -1,38 +1,25 @@ -/**************************************************************************** -** -** Copyright (C) 2021 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 <QTest> +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifdef QFLAGS_TEST_NO_TYPESAFE_FLAGS +# ifdef QT_TYPESAFE_FLAGS +# undef QT_TYPESAFE_FLAGS +# endif +#else +# ifndef QT_TYPESAFE_FLAGS +# define QT_TYPESAFE_FLAGS +# endif +#endif -QT_WARNING_DISABLE_DEPRECATED +#include <QTest> class tst_QFlags: public QObject { Q_OBJECT private slots: + void boolCasts() const; + void operators() const; + void mixingDifferentEnums() const; void testFlag() const; void testFlagZeroFlag() const; void testFlagMultiBits() const; @@ -46,6 +33,105 @@ private slots: void adl(); }; +void tst_QFlags::boolCasts() const +{ + // This tests that the operator overloading is sufficient so that common + // idioms involving flags -> bool casts work as expected: + + const Qt::Alignment nonNull = Qt::AlignCenter; + const Qt::Alignment null = {}; + + // basic premiss: + QVERIFY(bool(nonNull)); + QVERIFY(!bool(null)); + + // The rest is just checking that stuff compiles: + + // QVERIFY should compile: + QVERIFY(nonNull); + QVERIFY(!null); + + // ifs should compile: + if (null) QFAIL("Can't contextually convert QFlags to bool!"); + if (!nonNull) QFAIL("Missing operator! on QFlags (shouldn't be necessary)."); + + // ternary should compile: + QVERIFY(nonNull ? true : false); + QVERIFY(!null ? true : false); + + // logical operators should compile: + QVERIFY(nonNull && true); + QVERIFY(nonNull || false); + QVERIFY(!null && true); + QVERIFY(!null || false); + + // ... in both directions: + QVERIFY(true && nonNull); + QVERIFY(false || nonNull); + QVERIFY(true && !null); + QVERIFY(false || !null); + + // ... and mixed: + QVERIFY(null || nonNull); + QVERIFY(!(null && nonNull)); +} + +void tst_QFlags::operators() const +{ +#define CHECK(op, LHS, RHS, RES) \ + do { \ + QCOMPARE((LHS op RHS), (RES)); \ + QCOMPARE(( /*CTAD*/ QFlags(LHS) op RHS), (RES)); \ + QCOMPARE((LHS op QFlags(RHS)), (RES)); \ + QCOMPARE((QFlags(LHS) op QFlags(RHS)), (RES)); \ + QCOMPARE((QFlags(LHS) op ## = RHS), (RES)); \ + QCOMPARE((QFlags(LHS) op ## = QFlags(RHS)), (RES)); \ + } while (false) + + CHECK(|, Qt::AlignHCenter, Qt::AlignVCenter, Qt::AlignCenter); + CHECK(|, Qt::AlignHCenter, Qt::AlignHCenter, Qt::AlignHCenter); + CHECK(&, Qt::AlignHCenter, Qt::AlignVCenter, Qt::Alignment()); + CHECK(&, Qt::AlignHCenter, Qt::AlignHCenter, Qt::AlignHCenter); + CHECK(^, Qt::AlignHCenter, Qt::AlignVCenter, Qt::AlignCenter); + CHECK(^, Qt::AlignHCenter, Qt::AlignHCenter, Qt::Alignment()); +#undef CHECK +} + +void tst_QFlags::mixingDifferentEnums() const +{ +#define CHECK(op, LHS, RHS, RES) \ + /* LHS must be QFlags'able */ \ + do { \ + QCOMPARE((LHS op RHS), (RES)); \ + QCOMPARE((RHS op LHS), (RES)); \ + /*QCOMPARE(( / *CTAD* / QFlags(LHS) op RHS), (RES));*/ \ + /*QCOMPARE((QFlags(LHS) op ## = RHS), (RES));*/ \ + } while (false) + + // AlignmentFlags <-> TextFlags + { + CHECK(|, Qt::AlignCenter, Qt::TextSingleLine, 0x0184); + CHECK(&, Qt::AlignCenter, Qt::TextSingleLine, 0x0000); + CHECK(^, Qt::AlignCenter, Qt::TextSingleLine, 0x0184); + } + // QFlags<AlignmentFlags> <-> TextFlags + { +#ifndef QT_TYPESAFE_FLAGS // QTBUG-101344 + Qt::Alignment MyAlignCenter = Qt::AlignCenter; // convert enum to QFlags + CHECK(|, MyAlignCenter, Qt::TextSingleLine, 0x0184U); // yes, unsigned! + CHECK(&, MyAlignCenter, Qt::TextSingleLine, 0x0000U); // yes, unsigned! + CHECK(^, MyAlignCenter, Qt::TextSingleLine, 0x0184U); // yes, unsigned! +#endif + } + // TextElideMode <-> TextFlags + { + CHECK(|, Qt::ElideNone, Qt::TextSingleLine, 0x0103); + CHECK(&, Qt::ElideNone, Qt::TextSingleLine, 0x0000); + CHECK(^, Qt::ElideNone, Qt::TextSingleLine, 0x0103); + } +#undef CHECK +} + void tst_QFlags::testFlag() const { Qt::MouseButtons btn = Qt::LeftButton | Qt::RightButton; @@ -150,6 +236,7 @@ void tst_QFlags::testAnyFlag() } template <unsigned int N, typename T> bool verifyConstExpr(T n) { return n == N; } +template <unsigned int N, typename T> bool verifyConstExpr(QFlags<T> n) { return n.toInt() == N; } constexpr Qt::MouseButtons testRelaxedConstExpr() { @@ -164,25 +251,32 @@ constexpr Qt::MouseButtons testRelaxedConstExpr() void tst_QFlags::constExpr() { Qt::MouseButtons btn = Qt::LeftButton | Qt::RightButton; - switch (btn) { + switch (btn.toInt()) { case Qt::LeftButton: QVERIFY(false); break; case Qt::RightButton: QVERIFY(false); break; - case int(Qt::LeftButton | Qt::RightButton): QVERIFY(true); break; - default: QFAIL(qPrintable(QStringLiteral("Unexpected button: %1").arg(btn))); + case (Qt::LeftButton | Qt::RightButton).toInt(): QVERIFY(true); break; + default: QFAIL(qPrintable(QStringLiteral("Unexpected button: %1").arg(btn.toInt()))); } - QVERIFY(verifyConstExpr<uint((Qt::LeftButton | Qt::RightButton) & Qt::LeftButton)>(Qt::LeftButton)); - QVERIFY(verifyConstExpr<uint((Qt::LeftButton | Qt::RightButton) & Qt::MiddleButton)>(0)); - QVERIFY(verifyConstExpr<uint((Qt::LeftButton | Qt::RightButton) | Qt::MiddleButton)>(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton)); - QVERIFY(verifyConstExpr<uint(~(Qt::LeftButton | Qt::RightButton))>(~(Qt::LeftButton | Qt::RightButton))); - QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::LeftButton) ^ Qt::RightButton)>(Qt::LeftButton ^ Qt::RightButton)); - QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(0))>(0)); - QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::RightButton) & 0xff)>(Qt::RightButton)); - QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::RightButton) | 0xff)>(0xff)); +#define VERIFY_CONSTEXPR(expression, expected) \ + QVERIFY(verifyConstExpr<(expression).toInt()>(expected)) + + VERIFY_CONSTEXPR((Qt::LeftButton | Qt::RightButton) & Qt::LeftButton, Qt::LeftButton); + VERIFY_CONSTEXPR((Qt::LeftButton | Qt::RightButton) & Qt::MiddleButton, 0); + VERIFY_CONSTEXPR((Qt::LeftButton | Qt::RightButton) | Qt::MiddleButton, Qt::LeftButton | Qt::RightButton | Qt::MiddleButton); + VERIFY_CONSTEXPR(~(Qt::LeftButton | Qt::RightButton), ~(Qt::LeftButton | Qt::RightButton)); + VERIFY_CONSTEXPR(Qt::MouseButtons(Qt::LeftButton) ^ Qt::RightButton, Qt::LeftButton ^ Qt::RightButton); + VERIFY_CONSTEXPR(Qt::MouseButtons(0), 0); +#ifndef QT_TYPESAFE_FLAGS + QVERIFY(verifyConstExpr<(Qt::MouseButtons(Qt::RightButton) & 0xff)>(Qt::RightButton)); + QVERIFY(verifyConstExpr<(Qt::MouseButtons(Qt::RightButton) | 0xff)>(0xff)); +#endif QVERIFY(!verifyConstExpr<Qt::RightButton>(~Qt::MouseButtons(Qt::LeftButton))); - QVERIFY(verifyConstExpr<uint(testRelaxedConstExpr())>(Qt::MiddleButton)); + VERIFY_CONSTEXPR(testRelaxedConstExpr(), Qt::MiddleButton); + +#undef VERIFY_CONSTEXPR } void tst_QFlags::signedness() @@ -207,7 +301,7 @@ Q_DECLARE_FLAGS( MyStrictNoOpFlags, MyStrictNoOpEnum ) static_assert( !QTypeInfo<MyStrictFlags>::isComplex ); static_assert( QTypeInfo<MyStrictFlags>::isRelocatable ); -static_assert( !QTypeInfo<MyStrictFlags>::isPointer ); +static_assert( !std::is_pointer_v<MyStrictFlags> ); void tst_QFlags::classEnum() { @@ -233,11 +327,14 @@ void tst_QFlags::classEnum() QVERIFY(!f0); +#ifndef QT_TYPESAFE_FLAGS QCOMPARE(f3 & int(1), 1); QCOMPARE(f3 & uint(1), 1); +#endif QCOMPARE(f3 & MyStrictEnum::StrictOne, 1); MyStrictFlags aux; +#ifndef QT_TYPESAFE_FLAGS aux = f3; aux &= int(1); QCOMPARE(aux, 1); @@ -245,6 +342,7 @@ void tst_QFlags::classEnum() aux = f3; aux &= uint(1); QCOMPARE(aux, 1); +#endif aux = f3; aux &= MyStrictEnum::StrictOne; @@ -377,7 +475,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( MyFlags ) static_assert( !QTypeInfo<MyFlags>::isComplex ); static_assert( QTypeInfo<MyFlags>::isRelocatable ); -static_assert( !QTypeInfo<MyFlags>::isPointer ); +static_assert( !std::is_pointer_v<MyFlags> ); QTEST_MAIN(tst_QFlags) #include "tst_qflags.moc" diff --git a/tests/auto/corelib/global/qfloat16/CMakeLists.txt b/tests/auto/corelib/global/qfloat16/CMakeLists.txt index 1dbc95ec95..f6ca52b0df 100644 --- a/tests/auto/corelib/global/qfloat16/CMakeLists.txt +++ b/tests/auto/corelib/global/qfloat16/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qfloat16.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfloat16 Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfloat16 LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfloat16 SOURCES tst_qfloat16.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::TestPrivate ) diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index 90e131a7ef..7acf8c2cf6 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -1,34 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2016 by Southwest Research Institute (R) -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2016 by Southwest Research Institute (R) +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QFloat16> +#include <QMetaType> +#include <QTextStream> + +#include <private/qcomparisontesthelper_p.h> #include <math.h> @@ -41,6 +20,10 @@ class tst_qfloat16: public QObject Q_OBJECT private slots: + void compareCompiles(); + void relationalOperatorsAreConstexpr(); + void ordering_data(); + void ordering(); void fuzzyCompare_data(); void fuzzyCompare(); void fuzzyIsNull_data(); @@ -66,8 +49,180 @@ private slots: void properties(); void limits(); void mantissaOverflow(); + void dataStream(); + void textStream(); }; +void tst_qfloat16::compareCompiles() +{ + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, float>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, double>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, long double>(); +#if QFLOAT16_IS_NATIVE + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qfloat16::NativeType>(); +#endif + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, int>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint8>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint8>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint16>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint16>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, char16_t>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, long>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, unsigned long>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, wchar_t>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint32>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint32>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint64>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint64>(); +#ifdef QT_SUPPORTS_INT128 + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint128>(); + QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint128>(); +#endif +} + +void tst_qfloat16::relationalOperatorsAreConstexpr() +{ +#if QFLOAT16_IS_NATIVE + +#define CHECK_CONSTEXPR(Type) \ + do { \ + constexpr qfloat16 lhs = qfloat16(0.0f); \ + constexpr Type rhs = 1; \ + static_assert(lhs < rhs); \ + static_assert(rhs >= lhs); \ + } while (false) + + CHECK_CONSTEXPR(qfloat16); + CHECK_CONSTEXPR(float); + CHECK_CONSTEXPR(double); + CHECK_CONSTEXPR(long double); + CHECK_CONSTEXPR(qfloat16::NativeType); + CHECK_CONSTEXPR(qint8); + CHECK_CONSTEXPR(quint8); + CHECK_CONSTEXPR(qint16); + CHECK_CONSTEXPR(quint16); + CHECK_CONSTEXPR(qint32); + CHECK_CONSTEXPR(quint32); + CHECK_CONSTEXPR(long); + CHECK_CONSTEXPR(unsigned long); + CHECK_CONSTEXPR(qint64); + CHECK_CONSTEXPR(quint64); +#ifdef QT_SUPPORTS_INT128 + CHECK_CONSTEXPR(qint128); + CHECK_CONSTEXPR(quint128); +#endif + +#undef CHECK_CONSTEXPR + +#else + QSKIP("This check is only relevant for native float16 types"); +#endif // QFLOAT16_IS_NATIVE +} + +void tst_qfloat16::ordering_data() +{ + QTest::addColumn<float>("left"); + QTest::addColumn<float>("right"); + + auto row = [](float left, float right) { + QTest::addRow("%f_vs_%f", left, right) << left << right; + }; + + row(0.0f, 0.0f); + row(0.000001f, 0.0f); + row(0.0f, 0.000001f); + row(-1.000001f, 1.000001f); + const float nan = std::numeric_limits<float>::quiet_NaN(); + const float inf = std::numeric_limits<float>::infinity(); + row(nan, nan); + row(nan, inf); + row(inf, nan); + row(-inf, nan); + row(nan, -inf); + row(-inf, inf); + row(inf, -inf); + row(-inf, 0.0f); + row(0.0f, inf); + row(0.0f, nan); + row(nan, 0.0f); + row(2.0f, 314.159f); + row(-314.159f, 2.0f); + row(-2.0f, 314.159f); + row(nan, 314.159f); + row(-314.159f, inf); + row(-inf, 314.159f); + row(2.0f, -inf); + row(-2.0f, nan); + row(-inf, -2.0f); + // testing with values outside qfloat16 range + row(0.0f, 13e5f); + // generateRow(inf, 13e5f); // fails qfloat16 vs qfloat16 and qfloat16 vs int (QTBUG-118193) + row(0.0f, -13e5f); + // generateRow(-inf, -13e5f); // fails qfloat16 vs qfloat16 and qfloat16 vs int (QTBUG-118193) +} + +void tst_qfloat16::ordering() +{ + QFETCH(float, left); + QFETCH(float, right); + + const auto expectedOrder = Qt::compareThreeWay(left, right); + const auto lhs = qfloat16(left); + +#define POSTCHECK(msg) \ + if (QTest::currentTestFailed()) { qDebug(msg); return; } + +#define CHECK_FP(RHS) \ + do { \ + QTestPrivate::testAllComparisonOperators(lhs, static_cast<RHS>(right), expectedOrder); \ + POSTCHECK("qfloat16 vs " #RHS " comparison failed") \ + } while (false) \ + /* END */ + + CHECK_FP(qfloat16); + CHECK_FP(float); + CHECK_FP(double); + CHECK_FP(long double); + +#undef CHECK_FP + +#define CHECK_INT(RHS) \ + do { \ + const auto rhs = static_cast<RHS>(right); \ + const auto expectedRes = Qt::compareThreeWay(left, rhs); \ + QTestPrivate::testAllComparisonOperators(lhs, rhs, expectedRes); \ + POSTCHECK("qfloat16 vs " #RHS " comparison failed") \ + } while (false) \ + /* END */ + + if (qIsFinite(right)) { + CHECK_INT(int); + CHECK_INT(qint8); + CHECK_INT(signed char); + CHECK_INT(qint16); + CHECK_INT(qint32); + CHECK_INT(qint64); +#if QT_SUPPORTS_INT128 + CHECK_INT(qint128); +#endif + if (right >= 0) { + CHECK_INT(unsigned int); + CHECK_INT(quint8); + CHECK_INT(unsigned char); + CHECK_INT(quint16); + CHECK_INT(quint32); + CHECK_INT(quint64); + #if QT_SUPPORTS_INT128 + CHECK_INT(quint128); + #endif + } + } + +#undef CHECK_INT +#undef POSTCHECK +} + void tst_qfloat16::fuzzyCompare_data() { QTest::addColumn<qfloat16>("val1"); @@ -213,13 +368,7 @@ void tst_qfloat16::qNaN() QVERIFY(qIsNaN(nan)); QVERIFY(qIsNaN(nan + one)); QVERIFY(qIsNaN(-nan)); -#ifdef Q_CC_INTEL - QEXPECT_FAIL("", "ICC optimizes zero * anything to zero", Continue); -#endif QVERIFY(qIsNaN(nan * zero)); -#ifdef Q_CC_INTEL - QEXPECT_FAIL("", "ICC optimizes zero * anything to zero", Continue); -#endif QVERIFY(qIsNaN(Bounds::infinity() * zero)); QVERIFY(!nan.isNormal()); @@ -332,7 +481,7 @@ void tst_qfloat16::promotionTests() QCOMPARE(sizeof(double),sizeof(qfloat16(1.f)*1)); QCOMPARE(sizeof(double),sizeof(qfloat16(1.f)/1)); - QCOMPARE(QString::number(1.f),QString::number(qfloat16(1.f))); + QCOMPARE(QString::number(1.f),QString::number(double(qfloat16(1.f)))); } void tst_qfloat16::arithOps_data() @@ -550,17 +699,25 @@ void tst_qfloat16::properties() // and the same supposed to be for qfloat16. #if !defined(Q_CC_GHS) QVERIFY(Bounds::is_iec559); -#else +#endif //Q_CC_GHS +#if QT_CONFIG(signaling_nan) // Technically, presence of NaN and infinities are implied from the above check, but that checkings GHS compiler complies. QVERIFY(Bounds::has_infinity && Bounds::has_quiet_NaN && Bounds::has_signaling_NaN); -#endif // Q_CC_GHS +#endif QVERIFY(Bounds::is_bounded); QVERIFY(!Bounds::is_modulo); QVERIFY(!Bounds::traps); QVERIFY(Bounds::has_infinity); QVERIFY(Bounds::has_quiet_NaN); +#if QT_CONFIG(signaling_nan) QVERIFY(Bounds::has_signaling_NaN); +#endif +#if !defined(Q_CC_GHS) QCOMPARE(Bounds::has_denorm, std::denorm_present); +#else + // For GHS compiler the "denorm_indeterminite" is the expected return value. + QCOMPARE(Bounds::has_denorm, std::denorm_indeterminate); +#endif // Q_CC_GHS QCOMPARE(Bounds::round_style, std::round_to_nearest); QCOMPARE(Bounds::radix, 2); // Untested: has_denorm_loss @@ -647,12 +804,67 @@ void tst_qfloat16::mantissaOverflow() float f; memcpy(&f, &in, 4); - qfloat16 f16 = f; + qfloat16 f16 = qfloat16(f); qfloat16 f16s[1]; qFloatToFloat16(f16s, &f, 1); QCOMPARE(f16, f16s[0]); QVERIFY(qIsNaN(f16)); } +void tst_qfloat16::dataStream() +{ + QByteArray ba; + QDataStream ds(&ba, QIODevice::ReadWrite); + ds << qfloat16(1.5) << qfloat16(-1); + QCOMPARE(ba.size(), 4); + QCOMPARE(ds.status(), QDataStream::Ok); + QCOMPARE(ba, QByteArray("\x3e\0\xbc\0", 4)); + + ds.device()->seek(0); + ds.resetStatus(); + ds.setByteOrder(QDataStream::LittleEndian); + ds << qfloat16(0) << qfloat16(-1); + QCOMPARE(ds.status(), QDataStream::Ok); + QCOMPARE(ba, QByteArray("\0\0\0\xbc", 4)); + + ds.device()->seek(0); + ds.resetStatus(); + qfloat16 zero = 1; + ds >> zero; + QCOMPARE(ds.status(), QDataStream::Ok); + QCOMPARE(zero, qfloat16(0)); + + ds.device()->seek(0); + ds.resetStatus(); + QMetaType mt = QMetaType(QMetaType::Float16); + QVERIFY(mt.save(ds, &zero)); + + ds.device()->seek(0); + ds.resetStatus(); + zero = -1; + QVERIFY(mt.load(ds, &zero)); + QCOMPARE(zero, qfloat16(0)); +} + +void tst_qfloat16::textStream() +{ + QString buffer; + { + QTextStream ts(&buffer); + ts << qfloat16(0) << Qt::endl << qfloat16(1.5); + QCOMPARE(ts.status(), QTextStream::Ok); + } + QCOMPARE(buffer, "0\n1.5"); + + { + QTextStream ts(&buffer); + qfloat16 zero = qfloat16(-2.5), threehalves = 1234; + ts >> zero >> threehalves; + QCOMPARE(ts.status(), QTextStream::Ok); + QCOMPARE(zero, qfloat16(0)); + QCOMPARE(threehalves, 1.5); + } +} + QTEST_APPLESS_MAIN(tst_qfloat16) #include "tst_qfloat16.moc" diff --git a/tests/auto/corelib/global/qgetputenv/CMakeLists.txt b/tests/auto/corelib/global/qgetputenv/CMakeLists.txt index 79d45c58b0..f1a5cbeef3 100644 --- a/tests/auto/corelib/global/qgetputenv/CMakeLists.txt +++ b/tests/auto/corelib/global/qgetputenv/CMakeLists.txt @@ -1,9 +1,16 @@ -# Generated from qgetputenv.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgetputenv Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgetputenv LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgetputenv SOURCES tst_qgetputenv.cpp diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp index 519c5fa88d..96f2ce853c 100644 --- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp +++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qdebug.h> #include <QTest> @@ -85,7 +60,11 @@ void tst_QGetPutEnv::getSetCheck() QCOMPARE(sresult, QString()); #endif - QVERIFY(qputenv(varName, QByteArray("supervalue"))); + constexpr char varValueFullString[] = "supervalue123"; + const auto varValueQBA = QByteArray::fromRawData(varValueFullString, sizeof varValueFullString - 4); + QCOMPARE_EQ(varValueQBA, "supervalue"); + + QVERIFY(qputenv(varName, varValueQBA)); QVERIFY(qEnvironmentVariableIsSet(varName)); QVERIFY(!qEnvironmentVariableIsEmpty(varName)); @@ -212,7 +191,7 @@ void tst_QGetPutEnv::intValue() bool actualOk = !ok; // Self-test: confirm that it was like the docs said it should be - if (value.length() < maxlen) { + if (value.size() < maxlen) { QCOMPARE(value.toInt(&actualOk, 0), expected); QCOMPARE(actualOk, ok); } diff --git a/tests/auto/corelib/global/qglobal/CMakeLists.txt b/tests/auto/corelib/global/qglobal/CMakeLists.txt index de9a94629a..5a0877663b 100644 --- a/tests/auto/corelib/global/qglobal/CMakeLists.txt +++ b/tests/auto/corelib/global/qglobal/CMakeLists.txt @@ -1,13 +1,22 @@ -# Generated from qglobal.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qglobal Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qglobal LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qglobal SOURCES qglobal.c tst_qglobal.cpp + NO_PCH_SOURCES + tst_qglobal.cpp # undef QT_NO_FOREACH ) ## Scopes: diff --git a/tests/auto/corelib/global/qglobal/qglobal.c b/tests/auto/corelib/global/qglobal/qglobal.c index b577a6f71f..2cfbd5e3be 100644 --- a/tests/auto/corelib/global/qglobal/qglobal.c +++ b/tests/auto/corelib/global/qglobal/qglobal.c @@ -1,41 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/qglobal.h> - -#if __has_include(<stdbool.h>) || __STDC_VERSION__ >= 199901L -# include <stdbool.h> -#else -# undef true -# define true 1 -# undef false -# define false 0 -#endif +#include <QtCore/qtversion.h> +#include <QtCore/qyieldcpu.h> +#include <QtCore/qtypes.h> #ifdef Q_COMPILER_THREAD_LOCAL # include <threads.h> @@ -46,6 +15,11 @@ * everything works. */ +#if defined(Q_OS_VXWORKS) && !defined(thread_local) +// threads.h forgot to define this (should be fixed for version 23.11) +# define thread_local _Thread_local +#endif + /* Types and Q_UNUSED */ void tst_GlobalTypes() { @@ -77,15 +51,28 @@ void tst_GlobalTypes() qintptr qip; quintptr qup; Q_UNUSED(qs); Q_UNUSED(qp); Q_UNUSED(qip); Q_UNUSED(qup); + +#ifdef QT_SUPPORTS_INT128 + qint128 s128; + quint128 u128; + Q_UNUSED(s128); Q_UNUSED(u128); +#endif /* QT_SUPPORTS_INT128 */ } +#if QT_SUPPORTS_INT128 +qint128 tst_qint128_min() { return Q_INT128_MIN + 0; } +qint128 tst_qint128_max() { return 0 + Q_INT128_MAX; } +quint128 tst_quint128_max() { return Q_UINT128_MAX - 1 + 1; } +#endif + /* Qt version */ int tst_QtVersion() { return QT_VERSION; } -const char *tst_qVersion() Q_DECL_NOEXCEPT +const char *tst_qVersion() Q_DECL_NOEXCEPT; +const char *tst_qVersion() { #if !defined(QT_NAMESPACE) return qVersion(); @@ -94,6 +81,12 @@ const char *tst_qVersion() Q_DECL_NOEXCEPT #endif } +void tst_qYieldCpu(void) Q_DECL_NOEXCEPT; +void tst_qYieldCpu(void) +{ + qYieldCpu(); +} + /* Static assertion */ Q_STATIC_ASSERT(true); Q_STATIC_ASSERT(1); diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 7323cfe545..1a19048bbe 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -1,40 +1,20 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#undef QT_NO_FOREACH // this file tests Q_FOREACH! + #include <QTest> #include <QPair> #include <QSysInfo> #include <QLatin1String> #include <QString> +#include <QtVersion> #include <cmath> +#include <limits> +#include <type_traits> class tst_QGlobal: public QObject { @@ -52,6 +32,7 @@ private slots: void qCoreAppStartupFunction(); void qCoreAppStartupFunctionRestart(); void integerForSize(); + void int128Literals(); void buildAbiEndianness(); void testqOverload(); void testqMinMax(); @@ -61,12 +42,19 @@ private slots: void qRoundDoubles(); void PRImacros(); void testqToUnderlying(); + void nodiscard(); }; extern "C" { // functions in qglobal.c void tst_GlobalTypes(); int tst_QtVersion(); const char *tst_qVersion(); +#if QT_SUPPORTS_INT128 +qint128 tst_qint128_min(); +qint128 tst_qint128_max(); +quint128 tst_quint128_max(); +#endif + } void tst_QGlobal::cMode() @@ -109,7 +97,7 @@ void tst_QGlobal::for_each() foreach(int i, list) { QCOMPARE(i, counter++); } - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); // do it again, to make sure we don't have any for-scoping // problems with older compilers @@ -117,21 +105,21 @@ void tst_QGlobal::for_each() foreach(int i, list) { QCOMPARE(i, counter++); } - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); // check whether we can pass a constructor as container argument counter = 0; foreach (int i, QList<int>(list)) { QCOMPARE(i, counter++); } - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); // check whether we can use a lambda counter = 0; foreach (int i, [&](){ return list; }()) { QCOMPARE(i, counter++); } - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); // Should also work with an existing variable int local = 0; @@ -139,7 +127,7 @@ void tst_QGlobal::for_each() foreach (local, list) { QCOMPARE(local, counter++); } - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); QCOMPARE(local, counter - 1); // Test the macro does not mess if/else conditions @@ -149,7 +137,7 @@ void tst_QGlobal::for_each() QCOMPARE(i, counter++); else QFAIL("If/Else mismatch"); - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); counter = 0; if (false) @@ -160,7 +148,7 @@ void tst_QGlobal::for_each() foreach (int i, list) if (false) { } else QCOMPARE(i, counter++); - QCOMPARE(counter, list.count()); + QCOMPARE(counter, list.size()); // break and continue counter = 0; @@ -445,11 +433,166 @@ void tst_QGlobal::integerForSize() static_assert(sizeof(QIntegerForSize<2>::Signed) == 2); static_assert(sizeof(QIntegerForSize<4>::Signed) == 4); static_assert(sizeof(QIntegerForSize<8>::Signed) == 8); +#ifdef QT_SUPPORTS_INT128 + static_assert(sizeof(QIntegerForSize<16>::Signed) == 16); +#endif static_assert(sizeof(QIntegerForSize<1>::Unsigned) == 1); static_assert(sizeof(QIntegerForSize<2>::Unsigned) == 2); static_assert(sizeof(QIntegerForSize<4>::Unsigned) == 4); static_assert(sizeof(QIntegerForSize<8>::Unsigned) == 8); +#ifdef QT_SUPPORTS_INT128 + static_assert(sizeof(QIntegerForSize<16>::Unsigned) == 16); +#endif +} + +void tst_QGlobal::int128Literals() +{ +#ifdef QT_SUPPORTS_INT128 +#define COMPARE_EQ(lhs, rhs, Expected128) do { \ + constexpr auto lhs_ = lhs; \ + static_assert(std::is_same_v<std::remove_cv_t<decltype(lhs_)>, Expected128>); \ + QCOMPARE_EQ(lhs_, rhs); \ + } while (0) + COMPARE_EQ(Q_INT128_MIN, std::numeric_limits<qint128>::min(), qint128); + COMPARE_EQ(Q_INT128_MAX, std::numeric_limits<qint128>::max(), qint128); + COMPARE_EQ(Q_UINT128_MAX, std::numeric_limits<quint128>::max(), quint128); + QCOMPARE_EQ(tst_qint128_min(), Q_INT128_MIN); + QCOMPARE_EQ(tst_qint128_max(), Q_INT128_MAX); + QCOMPARE_EQ(tst_quint128_max(), Q_UINT128_MAX); + { + #define CHECK_S(x) COMPARE_EQ(Q_INT128_C(x), Q_INT64_C(x), qint128) + #define CHECK_U(x) COMPARE_EQ(Q_UINT128_C(x), Q_UINT64_C(x), quint128); + #define CHECK(x) do { CHECK_S(x); CHECK_U(x); } while (0) + // basics: + CHECK(0); + CHECK(1); + CHECK_S(-1); + QCOMPARE_EQ(Q_INT64_C(9223372036854775807), std::numeric_limits<qint64>::max()); + CHECK(9223372036854775807); // LLONG_MAX + // Q_INT64_C(-9223372036854775808) gives -Wimplicitly-unsigned-literal on GCC, so use numeric_limits: + { + constexpr auto i = Q_INT128_C(-9223372036854775808); // LLONG_MIN + static_assert(std::is_same_v<decltype(i), const qint128>); + QCOMPARE_EQ(i, std::numeric_limits<qint64>::min()); + } + // actual 128-bit numbers + { + constexpr auto i = Q_INT128_C( 9223372036854775808); // LLONG_MAX + 1 + constexpr auto u = Q_UINT128_C(9223372036854775808); // LLONG_MAX + 1 + static_assert(std::is_same_v<decltype(i), const qint128>); + static_assert(std::is_same_v<decltype(u), const quint128>); + QCOMPARE_EQ(i, qint128{ std::numeric_limits<qint64>::max()} + 1); + QCOMPARE_EQ(u, quint128{std::numeric_limits<qint64>::max()} + 1); + } + { + constexpr auto i = Q_INT128_C(-9223372036854775809); // LLONG_MIN - 1 + static_assert(std::is_same_v<decltype(i), const qint128>); + QCOMPARE_EQ(i, qint128{std::numeric_limits<qint64>::min()} - 1); + } + { + constexpr auto i = Q_INT128_C( 18446744073709551616); // ULLONG_MAX + 1 + constexpr auto u = Q_UINT128_C(18446744073709551616); + constexpr auto expected = qint128{1} << 64; + static_assert(std::is_same_v<decltype(i), const qint128>); + static_assert(std::is_same_v<decltype(expected), const qint128>); + static_assert(std::is_same_v<decltype(u), const quint128>); + QCOMPARE_EQ(i, expected); + QCOMPARE_EQ(u, quint128{expected}); + } + { + // compilers don't let one write signed _MIN literals, so use MIN + 1: + // Q_INT128_C(-170141183460469231731687303715884105728) gives + // ERROR: ~~~ outside range of representable values of type qint128 + // This is because the unary minus is technically speaking not part of + // the literal, but called on the result of the literal. + constexpr auto i = Q_INT128_C(-170141183460469231731687303715884105727); // 128-bit MIN + 1 + static_assert(std::is_same_v<decltype(i), const qint128>); + QCOMPARE_EQ(i, std::numeric_limits<qint128>::min() + 1); + } + { + constexpr auto i = Q_INT128_C( 170141183460469231731687303715884105727); // MAX + constexpr auto u = Q_UINT128_C(340282366920938463463374607431768211455); // UMAX + static_assert(std::is_same_v<decltype(i), const qint128>); + static_assert(std::is_same_v<decltype(u), const quint128>); + QCOMPARE_EQ(i, std::numeric_limits<qint128>::max()); + QCOMPARE_EQ(u, std::numeric_limits<quint128>::max()); + QCOMPARE_EQ(u, Q_UINT128_C(-1)); + } + + // binary literals: + CHECK(0b0); + CHECK(0b1); + CHECK_S(-0b1); + CHECK(0b01); + CHECK(0b10); + CHECK(0b1'1); // with digit separator + CHECK(0b0111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111); + //bytes |---1---| |---2---| |---3---| |---4---| |---5---| |---6---| |---7---| |---8---| + { + // bytes: |---1---| |---2---| |---3---| |---4---| |---5---| |---6---| |---7---| |---8---| |---9---| |--10---| |--11---| |--12---| |--13---| |--14---| |--15---| |--16---| + constexpr auto i = Q_INT128_C( 0b0111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111); + constexpr auto u = Q_UINT128_C(0b1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111); + static_assert(std::is_same_v<decltype(i), const qint128>); + static_assert(std::is_same_v<decltype(u), const quint128>); + QCOMPARE_EQ(i, std::numeric_limits<qint128>::max()); + QCOMPARE_EQ(u, std::numeric_limits<quint128>::max()); + QCOMPARE_EQ(u, Q_UINT128_C(-0b1)); + } + + // octal literals: + CHECK(00); + CHECK(01); + CHECK(02); + CHECK(03); + CHECK(04); + CHECK(05); + CHECK(06); + CHECK(07); + CHECK_S(-01); + CHECK(010); + CHECK_S(-01'0); // with digit separator + CHECK(07'7777'7777'7777'7777'7777); // LLONG_MAX + { + // bits: 120| 108| 96| 84| 72| 60| 48| 36| 24| 12| 0| + constexpr auto i = Q_INT128_C( 0177'7777'7777'7777'7777'7777'7777'7777'7777'7777'7777); + constexpr auto u = Q_UINT128_C(0377'7777'7777'7777'7777'7777'7777'7777'7777'7777'7777); + static_assert(std::is_same_v<decltype(i), const qint128>); + static_assert(std::is_same_v<decltype(u), const quint128>); + QCOMPARE_EQ(i, std::numeric_limits<qint128>::max()); + QCOMPARE_EQ(u, std::numeric_limits<quint128>::max()); + QCOMPARE_EQ(u, Q_UINT128_C(-01)); + } + + // hex literals: + CHECK(0x0); + CHECK(0x1); + CHECK(0x9); + CHECK(0xA); + CHECK(0xB); + CHECK(0xC); + CHECK(0xD); + CHECK(0xE); + CHECK(0x0F); + CHECK(0x10); + CHECK_S(-0x1); + CHECK_S(-0x1'0); // with digit separator + CHECK(0x7FFF'FFFF'FFFF'FFFF); + { + constexpr auto i = Q_INT128_C( 0x7FFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF); + constexpr auto u = Q_UINT128_C(0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF); + static_assert(std::is_same_v<decltype(i), const qint128>); + static_assert(std::is_same_v<decltype(u), const quint128>); + QCOMPARE_EQ(i, std::numeric_limits<qint128>::max()); + QCOMPARE_EQ(u, std::numeric_limits<quint128>::max()); + QCOMPARE_EQ(Q_UINT128_C(-1), u); + } + #undef CHECK + } +#undef COMPARE_EQ +#else + QSKIP("This test requires 128-bit integer support enabled in the compiler."); +#endif } typedef QPair<const char *, const char *> stringpair; @@ -715,5 +858,79 @@ void tst_QGlobal::testqToUnderlying() QCOMPARE(qToUnderlying(EE2), 456UL); } +void tst_QGlobal::nodiscard() +{ + // Syntax-only test, just to make sure that the Q_NODISCARD_* compile + // on all platforms. + // Other code is just to silence all various compiler warnings about + // unused private members or methods. + class Test { + public: + Q_NODISCARD_CTOR_X("Why construct a Test instead of just passing the int through?") + explicit Test(int val) : m_val(val) {} + Q_NODISCARD_CTOR explicit Test(float val) : m_val(int(val)) {} + + Q_NODISCARD_X("Why call get() if you don't use the returned value, hu?") // NOT idiomatic use! + int get() const { return m_val; } + + private: + int m_val; + }; + + Test t{42}; + QCOMPARE(t.get(), 42); + Test t2{42.0f}; + QCOMPARE(t2.get(), 42); +} + +QT_BEGIN_NAMESPACE + +// Compile-time typeinfo tests +struct Complex1 +{ + ~Complex1(); +}; +static_assert(QTypeInfo<Complex1>::isComplex); +static_assert(!QTypeInfo<Complex1>::isRelocatable); + +struct Complex2 +{ + Complex2(Complex2 &&); +}; +static_assert(QTypeInfo<Complex2>::isComplex); +static_assert(!QTypeInfo<Complex2>::isRelocatable); + +struct Complex3 +{ + Complex3(int); +}; +static_assert(QTypeInfo<Complex3>::isComplex); +static_assert(QTypeInfo<Complex3>::isRelocatable); + +struct Relocatable1 +{ + ~Relocatable1(); +}; +Q_DECLARE_TYPEINFO(Relocatable1, Q_RELOCATABLE_TYPE); +static_assert(QTypeInfo<Relocatable1>::isComplex); +static_assert(QTypeInfo<Relocatable1>::isRelocatable); + +struct Relocatable2 +{ + Relocatable2(int); +}; +Q_DECLARE_TYPEINFO(Relocatable2, Q_RELOCATABLE_TYPE); +static_assert(QTypeInfo<Relocatable2>::isComplex); +static_assert(QTypeInfo<Relocatable2>::isRelocatable); + +struct Trivial1 +{ + int x[42]; +}; +static_assert(!QTypeInfo<Trivial1>::isComplex); +static_assert(QTypeInfo<Trivial1>::isRelocatable); + +QT_END_NAMESPACE + QTEST_APPLESS_MAIN(tst_QGlobal) #include "tst_qglobal.moc" diff --git a/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt b/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt index ea978bdadb..6707e46dff 100644 --- a/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt +++ b/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt @@ -1,14 +1,21 @@ -# Generated from qglobalstatic.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qglobalstatic Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qglobalstatic LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qglobalstatic EXCEPTIONS SOURCES tst_qglobalstatic.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::TestPrivate ) diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp index ee85a3b77f..b8836668f5 100644 --- a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp +++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Thiago Macieira <thiago@kde.org> -** Copyright (C) 2016 Intel Corporation. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 Thiago Macieira <thiago@kde.org> +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QThread> #include <QTest> diff --git a/tests/auto/corelib/global/qhooks/CMakeLists.txt b/tests/auto/corelib/global/qhooks/CMakeLists.txt index c8d6f1a769..2d2051015f 100644 --- a/tests/auto/corelib/global/qhooks/CMakeLists.txt +++ b/tests/auto/corelib/global/qhooks/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qhooks.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qhooks Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qhooks LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qhooks SOURCES tst_qhooks.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate ) diff --git a/tests/auto/corelib/global/qhooks/tst_qhooks.cpp b/tests/auto/corelib/global/qhooks/tst_qhooks.cpp index 5a24275177..efdd9d7da1 100644 --- a/tests/auto/corelib/global/qhooks/tst_qhooks.cpp +++ b/tests/auto/corelib/global/qhooks/tst_qhooks.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module 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$ -** -****************************************************************************/ +// Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/global/qkeycombination/CMakeLists.txt b/tests/auto/corelib/global/qkeycombination/CMakeLists.txt index 9553a35dea..911eef7289 100644 --- a/tests/auto/corelib/global/qkeycombination/CMakeLists.txt +++ b/tests/auto/corelib/global/qkeycombination/CMakeLists.txt @@ -1,10 +1,19 @@ -# Generated from qkeycombination.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qkeycombination Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qkeycombination LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qkeycombination SOURCES tst_qkeycombination.cpp + LIBRARIES + Qt::TestPrivate ) diff --git a/tests/auto/corelib/global/qkeycombination/tst_qkeycombination.cpp b/tests/auto/corelib/global/qkeycombination/tst_qkeycombination.cpp index 7e70cdb70f..9941f8e154 100644 --- a/tests/auto/corelib/global/qkeycombination/tst_qkeycombination.cpp +++ b/tests/auto/corelib/global/qkeycombination/tst_qkeycombination.cpp @@ -1,38 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QObject> #include <QTest> +#include <QtTest/private/qcomparisontesthelper_p.h> class tst_QKeyCombination : public QObject { Q_OBJECT private slots: + void compareCompiles(); void construction(); void operator_eq(); void operator_or(); @@ -49,6 +26,11 @@ constexpr auto bitwiseOr(T ... args) return (... | ((int)args)); } +void tst_QKeyCombination::compareCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile<QKeyCombination>(); +} + void tst_QKeyCombination::construction() { { @@ -156,145 +138,125 @@ void tst_QKeyCombination::operator_eq() // default { QKeyCombination a, b; - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } // key only { QKeyCombination a; QKeyCombination b(Qt::Key_X); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::Key_Y); QKeyCombination b; - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::Key_Y); QKeyCombination b(Qt::Key_X); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::Key_F1); QKeyCombination b(Qt::Key_F1); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } // modifier only { QKeyCombination a; QKeyCombination b(Qt::CTRL); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::CTRL); QKeyCombination b; - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::CTRL); QKeyCombination b(Qt::SHIFT); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::CTRL); QKeyCombination b(Qt::CTRL); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } { QKeyCombination a(Qt::CTRL); QKeyCombination b(Qt::ControlModifier); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } { QKeyCombination a(Qt::ControlModifier); QKeyCombination b(Qt::CTRL); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } { QKeyCombination a(Qt::ControlModifier); QKeyCombination b(Qt::ControlModifier); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } // key and modifier { QKeyCombination a(Qt::Key_A); QKeyCombination b(Qt::SHIFT, Qt::Key_A); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::CTRL, Qt::Key_A); QKeyCombination b(Qt::SHIFT, Qt::Key_A); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::SHIFT, Qt::Key_A); QKeyCombination b(Qt::SHIFT, Qt::Key_A); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } { QKeyCombination a(Qt::SHIFT, Qt::Key_A); QKeyCombination b(Qt::SHIFT, Qt::Key_Escape); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::SHIFT, Qt::Key_A); QKeyCombination b(Qt::ShiftModifier, Qt::Key_A); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } { QKeyCombination a(Qt::SHIFT | Qt::CTRL, Qt::Key_A); QKeyCombination b(Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_A); - QVERIFY(a == b); - QVERIFY(!(a != b)); + QT_TEST_EQUALITY_OPS(a, b, true); } // corner cases { QKeyCombination a(Qt::CTRL); QKeyCombination b(Qt::Key_Control); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } { QKeyCombination a(Qt::ALT); QKeyCombination b(Qt::Key_Alt); - QVERIFY(a != b); - QVERIFY(!(a == b)); + QT_TEST_EQUALITY_OPS(a, b, false); } } diff --git a/tests/auto/corelib/global/qlogging/BLACKLIST b/tests/auto/corelib/global/qlogging/BLACKLIST index e2d930e37b..6cd7fc045d 100644 --- a/tests/auto/corelib/global/qlogging/BLACKLIST +++ b/tests/auto/corelib/global/qlogging/BLACKLIST @@ -1,9 +1,7 @@ [qMessagePattern:backtrace] -# QTBUG-63915 -b2qt 64bit +# QTBUG-121389 +b2qt 32bit [qMessagePattern:backtrace depth,separator] -# QTBUG-63915 -b2qt 64bit -# QTBUG-85364 -b2qt cmake +# QTBUG-121389 +b2qt 32bit diff --git a/tests/auto/corelib/global/qlogging/CMakeLists.txt b/tests/auto/corelib/global/qlogging/CMakeLists.txt index a9950d3414..f35c9c4192 100644 --- a/tests/auto/corelib/global/qlogging/CMakeLists.txt +++ b/tests/auto/corelib/global/qlogging/CMakeLists.txt @@ -1,6 +1,11 @@ -# Generated from qlogging.pro. -# This file is almost completely custom written -# special case skip regeneration +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlogging LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() qt_internal_add_executable(qlogging_helper NO_INSTALL @@ -18,12 +23,11 @@ set_target_properties(qlogging_helper PROPERTIES CXX_VISIBILITY_PRESET default) qt_internal_add_test(tst_qlogging SOURCES tst_qlogging.cpp DEFINES QT_MESSAGELOGCONTEXT - QT_DISABLE_DEPRECATED_BEFORE=0 - HELPER_BINARY="${CMAKE_CURRENT_BINARY_DIR}/qlogging_helper" ) +add_dependencies(tst_qlogging qlogging_helper) + qt_internal_add_test(tst_qmessagelogger SOURCES tst_qmessagelogger.cpp DEFINES QT_MESSAGELOGCONTEXT - QT_DISABLE_DEPRECATED_BEFORE=0 ) diff --git a/tests/auto/corelib/global/qlogging/app/main.cpp b/tests/auto/corelib/global/qlogging/app/main.cpp index 4c26bb85e3..e5b669e14f 100644 --- a/tests/auto/corelib/global/qlogging/app/main.cpp +++ b/tests/auto/corelib/global/qlogging/app/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QCoreApplication> #include <QLoggingCategory> diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index af4a5989d8..defe3ac421 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -1,31 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com> -** 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$ -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qdebug.h> #include <qglobal.h> @@ -33,6 +9,8 @@ # include <QtCore/QProcess> #endif #include <QtTest/QTest> +#include <QList> +#include <QMap> class tst_qmessagehandler : public QObject { @@ -52,6 +30,8 @@ private slots: #ifdef QT_BUILD_INTERNAL void cleanupFuncinfo_data(); void cleanupFuncinfo(); + void cleanupFuncinfoBad_data(); + void cleanupFuncinfoBad(); #endif void qMessagePattern_data(); @@ -62,7 +42,10 @@ private slots: void formatLogMessage(); private: - QStringList m_baseEnvironment; + QString backtraceHelperPath(); +#if QT_CONFIG(process) + QProcessEnvironment m_baseEnvironment; +#endif }; static QtMsgType s_type; @@ -89,13 +72,9 @@ tst_qmessagehandler::tst_qmessagehandler() void tst_qmessagehandler::initTestCase() { #if QT_CONFIG(process) - m_baseEnvironment = QProcess::systemEnvironment(); - for (int i = 0; i < m_baseEnvironment.count(); ++i) { - if (m_baseEnvironment.at(i).startsWith("QT_MESSAGE_PATTERN=")) { - m_baseEnvironment.removeAt(i); - break; - } - } + m_baseEnvironment = QProcessEnvironment::systemEnvironment(); + m_baseEnvironment.remove("QT_MESSAGE_PATTERN"); + m_baseEnvironment.insert("QT_FORCE_STDERR_LOGGING", "1"); #endif // QT_CONFIG(process) } @@ -189,9 +168,13 @@ public: int operator%(int) { ADD("TestClass1::operator%"); return 0; } int x; int &operator++() { ADD("TestClass1::operator++"); return x; } - int operator++(int) { ADD("TestClass1::operator++"); return 0; } int &operator--() { ADD("TestClass1::operator--"); return x; } - int operator--(int) { ADD("TestClass1::operator--"); return 0; } + + // slightly different to avoid duplicate test rows +#define ADD2(x) QTest::newRow(x ".postfix") << Q_FUNC_INFO << x; + int operator++(int) { ADD2("TestClass1::operator++"); return 0; } + int operator--(int) { ADD2("TestClass1::operator--"); return 0; } +#undef ADD2 int nested_struct() { @@ -553,7 +536,7 @@ void tst_qmessagehandler::cleanupFuncinfo_data() QTest::newRow("msvc_28") << "class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > *__thiscall TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > >::func_template1<class TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > >>(void)" << "TestClass2::func_template1"; - QTest::newRow("gcc_21") + QTest::newRow("gcc_28") << "T* TestClass2<T>::func_template1() [with S = TestClass2<std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > > >, T = std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > >]" << "TestClass2::func_template1"; @@ -622,6 +605,34 @@ void tst_qmessagehandler::cleanupFuncinfo_data() << "int TestClass1::operator>(int)" << "TestClass1::operator>"; + QTest::newRow("gcc_40") + << "Polymorphic<void (*)(int)>::~Polymorphic()" + << "Polymorphic::~Polymorphic"; + + QTest::newRow("gcc_41") + << "function<void (int*)>()::S::f()" + << "function()::S::f"; + + QTest::newRow("msvc_41") + << "void `void function<void __cdecl(int *)>(void)'::`2'::S::f(void)" + << "function(void)'::`2'::S::f"; + + QTest::newRow("gcc_42") + << "function<Polymorphic<void (int*)> >()::S::f(Polymorphic<void (int*)>*)" + << "function()::S::f"; + + QTest::newRow("msvc_42") + << "void `void function<Polymorphic<void __cdecl(int *)> >(void)'::`2'::S::f(Polymorphic<void __cdecl(int *)> *)" + << "function(void)'::`2'::S::f"; + + QTest::newRow("gcc_lambda_1") << "main(int, char**)::<lambda()>" + << "main(int, char**)::<lambda()>"; + + QTest::newRow("gcc_lambda_with_auto_1") + << "SomeClass::someMethod(const QString&, const QString&)::<lambda(auto:57)> [with " + "auto:57 = QNetworkReply::NetworkError]" + << "SomeClass::someMethod(const QString&, const QString&)::<lambda(auto:57)>"; + QTest::newRow("objc_1") << "-[SomeClass someMethod:withArguments:]" << "-[SomeClass someMethod:withArguments:]"; @@ -637,6 +648,14 @@ void tst_qmessagehandler::cleanupFuncinfo_data() QTest::newRow("objc_4") << "__31-[SomeClass someMethodSchedulingBlock]_block_invoke" << "__31-[SomeClass someMethodSchedulingBlock]_block_invoke"; + + QTest::newRow("thunk-1") + << "non-virtual thunk to QFutureWatcherBasePrivate::postCallOutEvent(QFutureCallOutEvent const&)" + << "QFutureWatcherBasePrivate::postCallOutEvent"; + + QTest::newRow("thunk-2") + << "virtual thunk to std::basic_iostream<char, std::char_traits<char> >::~basic_iostream()" + << "std::basic_iostream::~basic_iostream"; } #endif @@ -657,6 +676,41 @@ void tst_qmessagehandler::cleanupFuncinfo() QEXPECT_FAIL("TestClass1::nested_struct_const", "Nested function processing is broken", Continue); QTEST(QString::fromLatin1(result), "expected"); } + +void tst_qmessagehandler::cleanupFuncinfoBad_data() +{ + QTest::addColumn<QByteArray>("funcinfo"); + + auto addBadFrame = [i = 0](const char *symbol) mutable { + QTest::addRow("%d", ++i) << QByteArray(symbol); + }; + addBadFrame("typeinfo for QEventLoop"); + addBadFrame("typeinfo name for QtPrivate::ResultStoreBase"); + addBadFrame("typeinfo name for ._anon_476"); + addBadFrame("typeinfo name for std::__1::__function::__base<bool (void*, void*)>"); + addBadFrame("vtable for BezierEase"); + addBadFrame("vtable for Polymorphic<void ()>"); + addBadFrame("vtable for Polymorphic<void (*)(int)>"); + addBadFrame("TLS wrapper function for (anonymous namespace)::jitStacks"); + addBadFrame("lcCheckIndex()::category"); + addBadFrame("guard variable for lcEPDetach()::category"); + addBadFrame("guard variable for QImageReader::read(QImage*)::disableNxImageLoading"); + addBadFrame("VTT for std::__1::ostrstream"); + addBadFrame("qIsRelocatable<(anonymous namespace)::Data>"); + addBadFrame("qt_incomplete_metaTypeArray<(anonymous namespace)::qt_meta_stringdata_CLASSQNonContiguousByteDeviceIoDeviceImplENDCLASS_t, QtPrivate::TypeAndForceComplete<void, std::integral_constant<bool, true> > >"); + addBadFrame("f()::i"); +} + +void tst_qmessagehandler::cleanupFuncinfoBad() +{ + QFETCH(QByteArray, funcinfo); + + // A corrupted stack trace may find non-sensical symbols that aren't + // functions. The result doesn't matter, so long as we don't crash or hang. + + QByteArray result = qCleanupFuncinfo(funcinfo); + qDebug() << "Decode of" << funcinfo << "produced" << result; +} #endif void tst_qmessagehandler::qMessagePattern_data() @@ -667,16 +721,16 @@ void tst_qmessagehandler::qMessagePattern_data() // %{file} is tricky because of shadow builds QTest::newRow("basic") << "%{type} %{appname} %{line} %{function} %{message}" << true << (QList<QByteArray>() - << "debug 39 T::T static constructor" + << "debug 14 T::T static constructor" // we can't be sure whether the QT_MESSAGE_PATTERN is already destructed << "static destructor" - << "debug tst_qlogging 60 MyClass::myFunction from_a_function 34" - << "debug tst_qlogging 70 main qDebug" - << "info tst_qlogging 71 main qInfo" - << "warning tst_qlogging 72 main qWarning" - << "critical tst_qlogging 73 main qCritical" - << "warning tst_qlogging 76 main qDebug with category" - << "debug tst_qlogging 80 main qDebug2"); + << "debug tst_qlogging 35 MyClass::myFunction from_a_function 34" + << "debug tst_qlogging 45 main qDebug" + << "info tst_qlogging 46 main qInfo" + << "warning tst_qlogging 47 main qWarning" + << "critical tst_qlogging 48 main qCritical" + << "warning tst_qlogging 51 main qDebug with category" + << "debug tst_qlogging 55 main qDebug2"); QTest::newRow("invalid") << "PREFIX: %{unknown} %{message}" << false << (QList<QByteArray>() @@ -739,28 +793,42 @@ void tst_qmessagehandler::qMessagePattern_data() #define BACKTRACE_HELPER_NAME "qlogging_helper" -#ifdef __GLIBC__ #ifdef QT_NAMESPACE #define QT_NAMESPACE_STR QT_STRINGIFY(QT_NAMESPACE::) #else #define QT_NAMESPACE_STR "" #endif -#if QT_CONFIG(static) - QSKIP("These test cases don't work with static Qt builds"); -#else -#ifndef QT_NO_DEBUG - QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << (QList<QByteArray>() - // MyClass::qt_static_metacall is explicitly marked as hidden in the Q_OBJECT macro - << "[MyClass::myFunction|MyClass::mySlot1|?" BACKTRACE_HELPER_NAME "?|" QT_NAMESPACE_STR "QMetaMethod::invoke|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34"); -#endif +#ifdef __GLIBC__ +# if QT_CONFIG(static) + // These test cases don't work with static Qt builds +# elif !defined(Q_PROCESSOR_X86) + // On most RISC platforms, call frames do not have to be stored to the + // stack (the return pointer may be saved in any callee-saved register), so + // this test isn't reliable. +# elif defined(QT_ASAN_ENABLED) + // These tests produce far more call frames under ASan +# else +# ifndef QT_NO_DEBUG + QList<QByteArray> expectedBacktrace = { + // MyClass::qt_static_metacall is explicitly marked as hidden in the + // Q_OBJECT macro hence the ?helper? frame + "[MyClass::myFunction|MyClass::mySlot1|?" BACKTRACE_HELPER_NAME "?|", + + // QMetaObject::invokeMethodImpl calls internal function + // (QMetaMethodPrivate::invokeImpl, at the time of this writing), which + // will usually show only as ?libQt6Core.so? or equivalent, so we skip + + "|" QT_NAMESPACE_STR "QMetaObject::invokeMethodImpl] from_a_function 34" + }; + QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << expectedBacktrace; +# endif QTest::newRow("backtrace depth,separator") << "[%{backtrace depth=2 separator=\"\n\"}] %{message}" << true << (QList<QByteArray>() << "[MyClass::myFunction\nMyClass::mySlot1] from_a_function 34" << "[T::T\n"); -#endif // #if !QT_CONFIG(process) +# endif // #if !QT_CONFIG(static) #endif // #ifdef __GLIBC__ - } @@ -777,18 +845,14 @@ void tst_qmessagehandler::qMessagePattern() QFETCH(QList<QByteArray>, expected); QProcess process; -#ifndef Q_OS_ANDROID - const QString appExe(QLatin1String(HELPER_BINARY)); -#else - const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/lib" BACKTRACE_HELPER_NAME ".so")); -#endif + const QString appExe(backtraceHelperPath()); // // test QT_MESSAGE_PATTERN // - QStringList environment = m_baseEnvironment; - environment.prepend("QT_MESSAGE_PATTERN=\"" + pattern + QLatin1Char('"')); - process.setEnvironment(environment); + QProcessEnvironment environment = m_baseEnvironment; + environment.insert("QT_MESSAGE_PATTERN", pattern); + process.setProcessEnvironment(environment); process.start(appExe); QVERIFY2(process.waitForStarted(), qPrintable( @@ -801,15 +865,16 @@ void tst_qmessagehandler::qMessagePattern() QVERIFY(!output.isEmpty()); QCOMPARE(!output.contains("QT_MESSAGE_PATTERN"), valid); - for (const QByteArray &e : qAsConst(expected)) { + for (const QByteArray &e : std::as_const(expected)) { if (!output.contains(e)) { - qDebug() << output; - qDebug() << "expected: " << e; - QVERIFY(output.contains(e)); + // use QDebug so we get proper string escaping for the newlines + QString buf; + QDebug(&buf) << "Got:" << output << "; Expected:" << e; + QVERIFY2(output.contains(e), qPrintable(buf)); } } if (pattern.startsWith("%{pid}")) - QVERIFY2(output.startsWith('"' + pid), "PID: " + pid + "\noutput:\n" + output); + QVERIFY2(output.startsWith(pid), "PID: " + pid + "\noutput:\n" + output); #endif } @@ -827,22 +892,10 @@ void tst_qmessagehandler::setMessagePattern() // QProcess process; -#ifndef Q_OS_ANDROID - const QString appExe(QLatin1String(HELPER_BINARY)); -#else - const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so")); -#endif + const QString appExe(backtraceHelperPath()); // make sure there is no QT_MESSAGE_PATTERN in the environment - QStringList environment; - environment.reserve(m_baseEnvironment.size()); - const auto doesNotStartWith = [](QLatin1String s) { - return [s](const QString &str) { return !str.startsWith(s); }; - }; - std::copy_if(m_baseEnvironment.cbegin(), m_baseEnvironment.cend(), - std::back_inserter(environment), - doesNotStartWith(QLatin1String("QT_MESSAGE_PATTERN"))); - process.setEnvironment(environment); + process.setProcessEnvironment(m_baseEnvironment); process.start(appExe); QVERIFY2(process.waitForStarted(), qPrintable( @@ -928,6 +981,17 @@ void tst_qmessagehandler::formatLogMessage() QCOMPARE(r, result); } +QString tst_qmessagehandler::backtraceHelperPath() +{ +#ifdef Q_OS_ANDROID + QString appExe(QCoreApplication::applicationDirPath() + + QLatin1String("/lib" BACKTRACE_HELPER_NAME ".so")); +#else + QString appExe(QCoreApplication::applicationDirPath() + + QLatin1String("/" BACKTRACE_HELPER_NAME)); +#endif + return appExe; +} QTEST_MAIN(tst_qmessagehandler) #include "tst_qlogging.moc" diff --git a/tests/auto/corelib/global/qlogging/tst_qmessagelogger.cpp b/tests/auto/corelib/global/qlogging/tst_qmessagelogger.cpp index 4ff0469a49..9c6b9e275d 100644 --- a/tests/auto/corelib/global/qlogging/tst_qmessagelogger.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qmessagelogger.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qlogging.h> #include <qloggingcategory.h> diff --git a/tests/auto/corelib/global/qnativeinterface/CMakeLists.txt b/tests/auto/corelib/global/qnativeinterface/CMakeLists.txt index 52242b4292..2c87e07b21 100644 --- a/tests/auto/corelib/global/qnativeinterface/CMakeLists.txt +++ b/tests/auto/corelib/global/qnativeinterface/CMakeLists.txt @@ -1,3 +1,12 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qnativeinterface LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qnativeinterface SOURCES tst_qnativeinterface.cpp diff --git a/tests/auto/corelib/global/qnativeinterface/tst_qnativeinterface.cpp b/tests/auto/corelib/global/qnativeinterface/tst_qnativeinterface.cpp index 5291133406..602342770e 100644 --- a/tests/auto/corelib/global/qnativeinterface/tst_qnativeinterface.cpp +++ b/tests/auto/corelib/global/qnativeinterface/tst_qnativeinterface.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/global/qnumeric/CMakeLists.txt b/tests/auto/corelib/global/qnumeric/CMakeLists.txt index f86ddffc1d..e53a096c92 100644 --- a/tests/auto/corelib/global/qnumeric/CMakeLists.txt +++ b/tests/auto/corelib/global/qnumeric/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qnumeric.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qnumeric Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qnumeric LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qnumeric SOURCES tst_qnumeric.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate ) diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 5dbe6663b9..d21fabd74e 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -116,7 +91,7 @@ void tst_QNumeric::fuzzyCompare_data() QTest::addColumn<bool>("isEqual"); const F zero(0), one(1), ten(10); const F huge = Fuzzy<F>::scale, tiny = one / huge; - const F deci(.1), giga(1e9), nano(1e-9), big(1e7), small(1e-10); + const F deci(.1f), giga(1e9f), nano(1e-9f), big(1e7f), small(1e-10f); QTest::newRow("zero") << zero << zero << true; QTest::newRow("ten") << ten << ten << true; @@ -179,6 +154,15 @@ void tst_QNumeric::fuzzyIsNull() QCOMPARE(::qFuzzyIsNull(-value), isNull); } +static void clearFpExceptions() +{ + // Call after any functions that exercise floating-point exceptions, such as + // sqrt(-1) or log(0). +#ifdef Q_OS_WIN + _clearfp(); +#endif +} + #if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) // turn -ffast-math off # pragma GCC optimize "no-fast-math" @@ -187,6 +171,7 @@ void tst_QNumeric::fuzzyIsNull() template<typename F> void tst_QNumeric::checkNaN(F nan) { + const auto cleanup = qScopeGuard([]() { clearFpExceptions(); }); #define CHECKNAN(value) \ do { \ const F v = (value); \ @@ -195,21 +180,23 @@ void tst_QNumeric::checkNaN(F nan) QVERIFY(!qIsFinite(v)); \ QVERIFY(!qIsInf(v)); \ } while (0) + const F zero(0), one(1), two(2); - QVERIFY(!(0 > nan)); - QVERIFY(!(0 < nan)); - QVERIFY(!(0 == nan)); + QVERIFY(!(zero > nan)); + QVERIFY(!(zero < nan)); + QVERIFY(!(zero == nan)); QVERIFY(!(nan == nan)); CHECKNAN(nan); - CHECKNAN(nan + 1); - CHECKNAN(nan - 1); + CHECKNAN(nan + one); + CHECKNAN(nan - one); CHECKNAN(-nan); - CHECKNAN(nan * 2.0); - CHECKNAN(nan / 2.0); - CHECKNAN(1.0 / nan); - CHECKNAN(0.0 / nan); - CHECKNAN(0.0 * nan); + CHECKNAN(nan * two); + CHECKNAN(nan / two); + CHECKNAN(one / nan); + CHECKNAN(zero / nan); + CHECKNAN(zero * nan); + CHECKNAN(sqrt(-one)); // When any NaN is expected, any NaN will do: QCOMPARE(nan, nan); @@ -297,6 +284,7 @@ void tst_QNumeric::generalNaN() template<typename F> void tst_QNumeric::infinity() { + const auto cleanup = qScopeGuard([]() { clearFpExceptions(); }); const F inf = qInf(); const F zero(0), one(1), two(2); QVERIFY(inf > zero); @@ -319,6 +307,7 @@ void tst_QNumeric::infinity() QCOMPARE(one / -inf, zero); QVERIFY(qIsNaN(zero * inf)); QVERIFY(qIsNaN(zero * -inf)); + QCOMPARE(log(zero), -inf); } template<typename F> @@ -332,8 +321,11 @@ void tst_QNumeric::classifyfp() QCOMPARE(qFpClassify(inf), FP_INFINITE); QCOMPARE(qFpClassify(-inf), FP_INFINITE); + QT_WARNING_PUSH; + QT_WARNING_DISABLE_MSVC(4056); QCOMPARE(qFpClassify(huge * two), FP_INFINITE); QCOMPARE(qFpClassify(huge * -two), FP_INFINITE); + QT_WARNING_POP; QCOMPARE(qFpClassify(one), FP_NORMAL); QCOMPARE(qFpClassify(huge), FP_NORMAL); @@ -402,6 +394,11 @@ void tst_QNumeric::distance() QFETCH(F, from); QFETCH(F, stop); QFETCH(Count, expectedDistance); + if constexpr (std::numeric_limits<F>::has_denorm != std::denorm_present) { + if (qstrcmp(QTest::currentDataTag(), "denormal") == 0) { + QSKIP("Skipping 'denorm' as this type lacks denormals on this system"); + } + } QCOMPARE(qFloatDistance(from, stop), expectedDistance); QCOMPARE(qFloatDistance(stop, from), expectedDistance); } @@ -440,33 +437,33 @@ template <typename Int> static void addOverflow_template() #define ADD_COMPARE_NONOVF(v1, v2, expected) \ do { \ - QCOMPARE(add_overflow(Int(v1), Int(v2), &r), false); \ + QCOMPARE(qAddOverflow(Int(v1), Int(v2), &r), false); \ QCOMPARE(r, Int(expected)); \ - QCOMPARE(add_overflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), false); \ + QCOMPARE(qAddOverflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), false); \ QCOMPARE(r, Int(expected)); \ - QCOMPARE(add_overflow<v2>(Int(v1), &r), false); \ + QCOMPARE(qAddOverflow<v2>(Int(v1), &r), false); \ QCOMPARE(r, Int(expected)); \ } while (false) #define ADD_COMPARE_OVF(v1, v2) \ do { \ - QCOMPARE(add_overflow(Int(v1), Int(v2), &r), true); \ - QCOMPARE(add_overflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), true); \ - QCOMPARE(add_overflow<v2>(Int(v1), &r), true); \ + QCOMPARE(qAddOverflow(Int(v1), Int(v2), &r), true); \ + QCOMPARE(qAddOverflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), true); \ + QCOMPARE(qAddOverflow<v2>(Int(v1), &r), true); \ } while (false) #define SUB_COMPARE_NONOVF(v1, v2, expected) \ do { \ - QCOMPARE(sub_overflow(Int(v1), Int(v2), &r), false); \ + QCOMPARE(qSubOverflow(Int(v1), Int(v2), &r), false); \ QCOMPARE(r, Int(expected)); \ - QCOMPARE(sub_overflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), false); \ + QCOMPARE(qSubOverflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), false); \ QCOMPARE(r, Int(expected)); \ - QCOMPARE(sub_overflow<v2>(Int(v1), &r), false); \ + QCOMPARE(qSubOverflow<v2>(Int(v1), &r), false); \ QCOMPARE(r, Int(expected)); \ } while (false) #define SUB_COMPARE_OVF(v1, v2) \ do { \ - QCOMPARE(sub_overflow(Int(v1), Int(v2), &r), true); \ - QCOMPARE(sub_overflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), true); \ - QCOMPARE(sub_overflow<v2>(Int(v1), &r), true); \ + QCOMPARE(qSubOverflow(Int(v1), Int(v2), &r), true); \ + QCOMPARE(qSubOverflow(Int(v1), (std::integral_constant<Int, Int(v2)>()), &r), true); \ + QCOMPARE(qSubOverflow<v2>(Int(v1), &r), true); \ } while (false) // basic values @@ -617,18 +614,18 @@ template <typename Int> static void mulOverflow_template() #define MUL_COMPARE_NONOVF(v1, v2, expected) \ do { \ - QCOMPARE(mul_overflow(Int(v1), Int(v2), &r), false); \ + QCOMPARE(qMulOverflow(Int(v1), Int(v2), &r), false); \ QCOMPARE(r, Int(expected)); \ - QCOMPARE(mul_overflow(Int(v1), (std::integral_constant<Int, v2>()), &r), false); \ + QCOMPARE(qMulOverflow(Int(v1), (std::integral_constant<Int, v2>()), &r), false); \ QCOMPARE(r, Int(expected)); \ - QCOMPARE(mul_overflow<v2>(Int(v1), &r), false); \ + QCOMPARE(qMulOverflow<v2>(Int(v1), &r), false); \ QCOMPARE(r, Int(expected)); \ } while (false); #define MUL_COMPARE_OVF(v1, v2) \ do { \ - QCOMPARE(mul_overflow(Int(v1), Int(v2), &r), true); \ - QCOMPARE(mul_overflow(Int(v1), (std::integral_constant<Int, v2>()), &r), true); \ - QCOMPARE(mul_overflow<v2>(Int(v1), &r), true); \ + QCOMPARE(qMulOverflow(Int(v1), Int(v2), &r), true); \ + QCOMPARE(qMulOverflow(Int(v1), (std::integral_constant<Int, v2>()), &r), true); \ + QCOMPARE(qMulOverflow<v2>(Int(v1), &r), true); \ } while (false); // basic multiplications @@ -729,28 +726,28 @@ void tst_QNumeric::signedOverflow() const int maxInt = std::numeric_limits<int>::max(); int r; - QCOMPARE(add_overflow(minInt + 1, int(-1), &r), false); - QCOMPARE(add_overflow(minInt, int(-1), &r), true); - QCOMPARE(add_overflow(minInt, minInt, &r), true); - QCOMPARE(add_overflow(maxInt - 1, int(1), &r), false); - QCOMPARE(add_overflow(maxInt, int(1), &r), true); - QCOMPARE(add_overflow(maxInt, maxInt, &r), true); - - QCOMPARE(sub_overflow(minInt + 1, int(1), &r), false); - QCOMPARE(sub_overflow(minInt, int(1), &r), true); - QCOMPARE(sub_overflow(minInt, maxInt, &r), true); - QCOMPARE(sub_overflow(maxInt - 1, int(-1), &r), false); - QCOMPARE(sub_overflow(maxInt, int(-1), &r), true); - QCOMPARE(sub_overflow(maxInt, minInt, &r), true); - - QCOMPARE(mul_overflow(minInt, int(1), &r), false); - QCOMPARE(mul_overflow(minInt, int(-1), &r), true); - QCOMPARE(mul_overflow(minInt, int(2), &r), true); - QCOMPARE(mul_overflow(minInt, minInt, &r), true); - QCOMPARE(mul_overflow(maxInt, int(1), &r), false); - QCOMPARE(mul_overflow(maxInt, int(-1), &r), false); - QCOMPARE(mul_overflow(maxInt, int(2), &r), true); - QCOMPARE(mul_overflow(maxInt, maxInt, &r), true); + QCOMPARE(qAddOverflow(minInt + 1, int(-1), &r), false); + QCOMPARE(qAddOverflow(minInt, int(-1), &r), true); + QCOMPARE(qAddOverflow(minInt, minInt, &r), true); + QCOMPARE(qAddOverflow(maxInt - 1, int(1), &r), false); + QCOMPARE(qAddOverflow(maxInt, int(1), &r), true); + QCOMPARE(qAddOverflow(maxInt, maxInt, &r), true); + + QCOMPARE(qSubOverflow(minInt + 1, int(1), &r), false); + QCOMPARE(qSubOverflow(minInt, int(1), &r), true); + QCOMPARE(qSubOverflow(minInt, maxInt, &r), true); + QCOMPARE(qSubOverflow(maxInt - 1, int(-1), &r), false); + QCOMPARE(qSubOverflow(maxInt, int(-1), &r), true); + QCOMPARE(qSubOverflow(maxInt, minInt, &r), true); + + QCOMPARE(qMulOverflow(minInt, int(1), &r), false); + QCOMPARE(qMulOverflow(minInt, int(-1), &r), true); + QCOMPARE(qMulOverflow(minInt, int(2), &r), true); + QCOMPARE(qMulOverflow(minInt, minInt, &r), true); + QCOMPARE(qMulOverflow(maxInt, int(1), &r), false); + QCOMPARE(qMulOverflow(maxInt, int(-1), &r), false); + QCOMPARE(qMulOverflow(maxInt, int(2), &r), true); + QCOMPARE(qMulOverflow(maxInt, maxInt, &r), true); } QTEST_APPLESS_MAIN(tst_QNumeric) diff --git a/tests/auto/corelib/global/qoperatingsystemversion/CMakeLists.txt b/tests/auto/corelib/global/qoperatingsystemversion/CMakeLists.txt index 619297fdab..f0e682d664 100644 --- a/tests/auto/corelib/global/qoperatingsystemversion/CMakeLists.txt +++ b/tests/auto/corelib/global/qoperatingsystemversion/CMakeLists.txt @@ -1,9 +1,16 @@ -# Generated from qoperatingsystemversion.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qoperatingsystemversion Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qoperatingsystemversion LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qoperatingsystemversion SOURCES tst_qoperatingsystemversion.cpp diff --git a/tests/auto/corelib/global/qoperatingsystemversion/tst_qoperatingsystemversion.cpp b/tests/auto/corelib/global/qoperatingsystemversion/tst_qoperatingsystemversion.cpp index d1f9279b57..4c4ff72722 100644 --- a/tests/auto/corelib/global/qoperatingsystemversion/tst_qoperatingsystemversion.cpp +++ b/tests/auto/corelib/global/qoperatingsystemversion/tst_qoperatingsystemversion.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <qoperatingsystemversion.h> @@ -35,11 +10,15 @@ class tst_QOperatingSystemVersion : public QObject private slots: void construction_data(); void construction(); + void globals_data(); + void globals(); void anyOf(); void comparison_data(); void comparison(); + void comparison2_data(); + void comparison2(); void mixedComparison(); }; @@ -77,6 +56,34 @@ void tst_QOperatingSystemVersion::construction() QVERIFY(!systemVersion.name().isEmpty()); } +void tst_QOperatingSystemVersion::globals_data() +{ + QTest::addColumn<QOperatingSystemVersion>("osver"); + QTest::addColumn<QOperatingSystemVersion::OSType>("osType"); + +#define ADDROW(os) QTest::newRow(#os) << QOperatingSystemVersion(QOperatingSystemVersion::os) + // legacy ones (global variables) + ADDROW(Windows7) << QOperatingSystemVersion::Windows; + ADDROW(Windows10) << QOperatingSystemVersion::Windows; + ADDROW(OSXMavericks) << QOperatingSystemVersion::MacOS; + ADDROW(MacOSMonterey) << QOperatingSystemVersion::MacOS; + ADDROW(AndroidJellyBean) << QOperatingSystemVersion::Android; + ADDROW(Android11) << QOperatingSystemVersion::Android; + + // new ones (static constexpr) + ADDROW(Windows11) << QOperatingSystemVersion::Windows; + ADDROW(Android12) << QOperatingSystemVersion::Android; +#undef ADDROW +} + +void tst_QOperatingSystemVersion::globals() +{ + QFETCH(QOperatingSystemVersion, osver); + QFETCH(QOperatingSystemVersion::OSType, osType); + QCOMPARE(osver.type(), osType); + QCOMPARE_NE(osver.majorVersion(), 0); +} + void tst_QOperatingSystemVersion::anyOf() { std::initializer_list<QOperatingSystemVersion::OSType> typesToCheck = { @@ -107,47 +114,44 @@ void tst_QOperatingSystemVersion::comparison_data() QTest::addColumn<int>("rhsMinor"); QTest::addColumn<int>("rhsMicro"); - QTest::addColumn<bool>("lessResult"); - QTest::addColumn<bool>("lessEqualResult"); - QTest::addColumn<bool>("moreResult"); - QTest::addColumn<bool>("moreEqualResult"); + QTest::addColumn<Qt::partial_ordering>("expectedResult"); QTest::addRow("mismatching types") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 << QOperatingSystemVersion::OSType::MacOS << 1 << 2 << 3 - << false << false << false << false; + << Qt::partial_ordering::unordered; QTest::addRow("equal versions") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 - << false << true << false << true; + << Qt::partial_ordering::equivalent; QTest::addRow("lhs micro less") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 2 << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 - << true << true << false << false; + << Qt::partial_ordering::less; QTest::addRow("rhs micro less") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 2 << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 1 - << false << false << true << true; + << Qt::partial_ordering::greater; QTest::addRow("lhs minor less") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 << QOperatingSystemVersion::OSType::Windows << 1 << 3 << 3 - << true << true << false << false; + << Qt::partial_ordering::less; QTest::addRow("rhs minor less") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 2 << QOperatingSystemVersion::OSType::Windows << 1 << 1 << 3 - << false << false << true << true; + << Qt::partial_ordering::greater; QTest::addRow("lhs major less") << QOperatingSystemVersion::OSType::Windows << 0 << 5 << 6 << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 - << true << true << false << false; + << Qt::partial_ordering::less; QTest::addRow("rhs major less") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 << QOperatingSystemVersion::OSType::Windows << 0 << 2 << 3 - << false << false << true << true; + << Qt::partial_ordering::greater; QTest::addRow("different segmentCount") << QOperatingSystemVersion::OSType::Windows << 1 << 2 << 3 << QOperatingSystemVersion::OSType::Windows << 1 << 2 << -1 - << false << true << false << true; + << Qt::partial_ordering::equivalent; } void tst_QOperatingSystemVersion::comparison() @@ -166,17 +170,75 @@ void tst_QOperatingSystemVersion::comparison() const QOperatingSystemVersion rhsSystemInfo(rhsType, rhsMajor, rhsMinor, rhsMicro); - QFETCH(bool, lessResult); - QCOMPARE(lhsSystemInfo < rhsSystemInfo, lessResult); + QFETCH(const Qt::partial_ordering, expectedResult); - QFETCH(bool, lessEqualResult); - QCOMPARE(lhsSystemInfo <= rhsSystemInfo, lessEqualResult); + QCOMPARE_EQ(lhsSystemInfo < rhsSystemInfo, is_lt(expectedResult)); + QCOMPARE_EQ(lhsSystemInfo <= rhsSystemInfo, is_lteq(expectedResult)); + QCOMPARE_EQ(lhsSystemInfo > rhsSystemInfo, is_gt(expectedResult)); + QCOMPARE_EQ(lhsSystemInfo >= rhsSystemInfo, is_gteq(expectedResult)); +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(lhsSystemInfo <=> rhsSystemInfo, expectedResult); +#endif +} - QFETCH(bool, moreResult); - QCOMPARE(lhsSystemInfo > rhsSystemInfo, moreResult); +void tst_QOperatingSystemVersion::comparison2_data() +{ + QTest::addColumn<QOperatingSystemVersion>("lhs"); + QTest::addColumn<QOperatingSystemVersion>("rhs"); + QTest::addColumn<Qt::partial_ordering>("result"); + +#define ADDROW(os1, os2) \ + QTest::newRow(#os1 "-vs-" #os2) << QOperatingSystemVersion(QOperatingSystemVersion::os1) \ + << QOperatingSystemVersion(QOperatingSystemVersion::os2) + + // Cross-OS testing: not comparables. + ADDROW(Windows10, MacOSMonterey) << Qt::partial_ordering::unordered; + ADDROW(Windows11, MacOSMonterey) << Qt::partial_ordering::unordered; + ADDROW(MacOSMonterey, Windows10) << Qt::partial_ordering::unordered; + ADDROW(MacOSMonterey, Windows11) << Qt::partial_ordering::unordered; + ADDROW(Windows10, MacOSVentura) << Qt::partial_ordering::unordered; + ADDROW(Windows11, MacOSVentura) << Qt::partial_ordering::unordered; + ADDROW(MacOSVentura, Windows10) << Qt::partial_ordering::unordered; + ADDROW(MacOSVentura, Windows11) << Qt::partial_ordering::unordered; + ADDROW(Windows10, Android10) << Qt::partial_ordering::unordered; + ADDROW(Windows11, Android11) << Qt::partial_ordering::unordered; + + // Same-OS tests. This list does not have to be exhaustive. + ADDROW(Windows7, Windows7) << Qt::partial_ordering::equivalent; + ADDROW(Windows7, Windows8) << Qt::partial_ordering::less; + ADDROW(Windows8, Windows7) << Qt::partial_ordering::greater; + ADDROW(Windows8, Windows10) << Qt::partial_ordering::less; + ADDROW(Windows10, Windows8) << Qt::partial_ordering::greater; + ADDROW(Windows10, Windows10_21H1) << Qt::partial_ordering::less; + ADDROW(Windows10_21H1, Windows10) << Qt::partial_ordering::greater; + ADDROW(Windows10, Windows11) << Qt::partial_ordering::less; + ADDROW(MacOSCatalina, MacOSCatalina) << Qt::partial_ordering::equivalent; + ADDROW(MacOSCatalina, MacOSBigSur) << Qt::partial_ordering::less; + ADDROW(MacOSBigSur, MacOSCatalina) << Qt::partial_ordering::greater; + ADDROW(MacOSMonterey, MacOSVentura) << Qt::partial_ordering::less; + ADDROW(MacOSVentura, MacOSVentura) << Qt::partial_ordering::equivalent; + ADDROW(MacOSVentura, MacOSMonterey) << Qt::partial_ordering::greater; +#undef ADDROW +} - QFETCH(bool, moreEqualResult); - QCOMPARE(lhsSystemInfo >= rhsSystemInfo, moreEqualResult); +void tst_QOperatingSystemVersion::comparison2() +{ + QFETCH(QOperatingSystemVersion, lhs); + QFETCH(QOperatingSystemVersion, rhs); + QFETCH(const Qt::partial_ordering, result); + + QEXPECT_FAIL("Windows10-vs-Windows10_21H1", "QTBUG-107907: Unexpected behavior", Abort); + QEXPECT_FAIL("Windows10-vs-Windows11", "QTBUG-107907: Unexpected behavior", Abort); + + const bool comparable = (result != Qt::partial_ordering::unordered); + QCOMPARE_EQ(lhs < rhs, is_lt(result) && comparable); + QEXPECT_FAIL("Windows10_21H1-vs-Windows10", "QTBUG-107907: Unexpected behavior", Abort); + QCOMPARE_EQ(lhs <= rhs, is_lteq(result) && comparable); + QCOMPARE_EQ(lhs > rhs, is_gt(result) && comparable); + QCOMPARE_EQ(lhs >= rhs, is_gteq(result) && comparable); +#ifdef __cpp_lib_three_way_comparison + QCOMPARE_EQ(lhs <=> rhs, result); +#endif } void tst_QOperatingSystemVersion::mixedComparison() diff --git a/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt b/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt index 54fa36b5df..3d8f892414 100644 --- a/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt +++ b/tests/auto/corelib/global/qrandomgenerator/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qrandomgenerator.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qrandomgenerator Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qrandomgenerator LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qrandomgenerator SOURCES tst_qrandomgenerator.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate ) diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp index 30e170b65d..a32045bbbb 100644 --- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp +++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <qlist.h> @@ -39,7 +14,6 @@ # define HAVE_FALLBACK_ENGINE #endif -#define COMMA , #define QVERIFY_3TIMES(statement) \ do {\ if (!static_cast<bool>(statement))\ @@ -154,6 +128,9 @@ void tst_QRandomGenerator::basics() QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wself-move") QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded") +#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1301 +QT_WARNING_DISABLE_GCC("-Wself-move") +#endif // copyable && movable rng = rng; rng = std::move(rng); @@ -190,8 +167,8 @@ QT_WARNING_POP QRandomGenerator64 systemRng64 = *system64; systemRng64 = *system64; - static_assert(std::is_same<decltype(rng64.generate()) COMMA quint64>::value); - static_assert(std::is_same<decltype(system64->generate()) COMMA quint64>::value); + static_assert(std::is_same_v<decltype(rng64.generate()), quint64>); + static_assert(std::is_same_v<decltype(system64->generate()), quint64>); } void tst_QRandomGenerator::knownSequence() @@ -636,7 +613,7 @@ template <typename UInt> static void boundedQuality_template() QVector<UInt> buffer(BufferCount, filler); generate(buffer.begin(), buffer.end(), [&] { return rng.bounded(Bound); }); - for (UInt value : qAsConst(buffer)) { + for (UInt value : std::as_const(buffer)) { QVERIFY(value < Bound); histogram[value]++; } @@ -920,18 +897,20 @@ void tst_QRandomGenerator::stdGenerateCanonical() { QFETCH(uint, control); RandomGenerator rng(control); + auto generate_canonical = [&rng]() { + return std::generate_canonical<qreal, 32>(rng); + }; for (int i = 0; i < 4; ++i) { QVERIFY_3TIMES([&] { - qreal value = std::generate_canonical<qreal COMMA 32>(rng); + qreal value = generate_canonical(); return value > 0 && value < 1 && value != RandomValueFP; }()); } // and should hopefully be different from repeated calls for (int i = 0; i < 4; ++i) - QVERIFY_3TIMES(std::generate_canonical<qreal COMMA 32>(rng) != - std::generate_canonical<qreal COMMA 32>(rng)); + QVERIFY_3TIMES(generate_canonical() != generate_canonical()); } void tst_QRandomGenerator::stdUniformRealDistribution_data() diff --git a/tests/auto/corelib/global/qtendian/CMakeLists.txt b/tests/auto/corelib/global/qtendian/CMakeLists.txt index acd0981991..cf1a22f678 100644 --- a/tests/auto/corelib/global/qtendian/CMakeLists.txt +++ b/tests/auto/corelib/global/qtendian/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qtendian.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtendian Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtendian LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtendian SOURCES tst_qtendian.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate ) diff --git a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp index 74c2deff52..8e50b2bd08 100644 --- a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp +++ b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp @@ -1,40 +1,27 @@ -/**************************************************************************** -** -** Copyright (C) 2021 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/qendian.h> #include <QtCore/private/qendian_p.h> +#include <QtCore/qsysinfo.h> +#if QT_SUPPORTS_INT128 +#define ONLY_INT128(...) __VA_ARGS__ +#else +#define ONLY_INT128(...) +#endif class tst_QtEndian: public QObject { Q_OBJECT +public: + enum Signedness { + Unsigned, + Signed + }; + Q_ENUM(Signedness); private slots: void fromBigEndian(); @@ -54,11 +41,15 @@ private slots: void endianIntegers_data(); void endianIntegers(); - void endianBitfields(); + void endianBitfieldUnions_data(); + void endianBitfieldUnions(); }; struct TestData { + ONLY_INT128( + quint128 data128; + ) quint64 data64; quint32 data32; quint16 data16; @@ -75,6 +66,9 @@ template <> quint8 getData(const TestData &d) { return d.data8; } template <> quint16 getData(const TestData &d) { return d.data16; } template <> quint32 getData(const TestData &d) { return d.data32; } template <> quint64 getData(const TestData &d) { return d.data64; } +ONLY_INT128( +template <> quint128 getData(const TestData &d) { return d.data128; } +) template <> float getData(const TestData &d) { return d.dataFloat; } union RawTestData @@ -92,6 +86,9 @@ Float int2Float(typename QIntegerForSizeof<Float>::Unsigned i) } static const TestData inNativeEndian = { + ONLY_INT128( + Q_UINT128_C(0x0123'4567'89ab'cdef'18ba'df00'd1da'cafe), + ) Q_UINT64_C(0x0123456789abcdef), 0x00c0ffee, 0xcafe, @@ -101,6 +98,9 @@ static const TestData inNativeEndian = { '\0' }; static const RawTestData inBigEndian = { + ONLY_INT128( + "\x01\x23\x45\x67\x89\xab\xcd\xef\x18\xba\xdf\x00\xd1\xda\xca\xfe" + ) "\x01\x23\x45\x67\x89\xab\xcd\xef" "\x00\xc0\xff\xee" "\xca\xfe" @@ -109,6 +109,9 @@ static const RawTestData inBigEndian = { "\x01\x23\x45\x67\x89\xab\xcd\xef" }; static const RawTestData inLittleEndian = { + ONLY_INT128( + "\xfe\xca\xda\xd1\x00\xdf\xba\x18\xef\xcd\xab\x89\x67\x45\x23\x01" + ) "\xef\xcd\xab\x89\x67\x45\x23\x01" "\xee\xff\xc0\x00" "\xfe\xca" @@ -120,27 +123,37 @@ static const RawTestData inLittleEndian = { #define EXPAND_ENDIAN_TEST(endian) \ do { \ /* Unsigned tests */ \ - ENDIAN_TEST(endian, quint, 64); \ - ENDIAN_TEST(endian, quint, 32); \ - ENDIAN_TEST(endian, quint, 16); \ - ENDIAN_TEST(endian, quint, 8); \ + ONLY_INT128( \ + ENDIAN_TEST_INT(endian, ui, 128); \ + ) \ + ENDIAN_TEST_INT(endian, ui, 64); \ + ENDIAN_TEST_INT(endian, ui, 32); \ + ENDIAN_TEST_INT(endian, ui, 16); \ + ENDIAN_TEST_INT(endian, ui, 8); \ \ /* Signed tests */ \ - ENDIAN_TEST(endian, qint, 64); \ - ENDIAN_TEST(endian, qint, 32); \ - ENDIAN_TEST(endian, qint, 16); \ - ENDIAN_TEST(endian, qint, 8); \ + ONLY_INT128( \ + ENDIAN_TEST_INT(endian, i, 128); \ + ) \ + ENDIAN_TEST_INT(endian, i, 64); \ + ENDIAN_TEST_INT(endian, i, 32); \ + ENDIAN_TEST_INT(endian, i, 16); \ + ENDIAN_TEST_INT(endian, i, 8); \ } while (false) \ /**/ -#define ENDIAN_TEST(endian, type, size) \ +#define ENDIAN_TEST_INT(Endian, Uns, Size) \ + ENDIAN_TEST(Endian, q ## Uns ## nt ## Size, data ## Size) + +#define ENDIAN_TEST(endian, Type, Data) \ do { \ + static_assert(std::is_same_v<decltype(qbswap(std::declval<Type>())), Type>); \ QCOMPARE(qFrom ## endian ## Endian( \ - (type ## size)(in ## endian ## Endian.data.data ## size)), \ - (type ## size)(inNativeEndian.data ## size)); \ - QCOMPARE(qFrom ## endian ## Endian<type ## size>( \ - in ## endian ## Endian.rawData + offsetof(TestData, data ## size)), \ - (type ## size)(inNativeEndian.data ## size)); \ + (Type)(in ## endian ## Endian.data.Data)), \ + (Type)(inNativeEndian.Data)); \ + QCOMPARE(qFrom ## endian ## Endian<Type>( \ + in ## endian ## Endian.rawData + offsetof(TestData, Data)), \ + (Type)(inNativeEndian.Data)); \ } while (false) \ /**/ @@ -261,18 +274,18 @@ void tst_QtEndian::fromLittleEndianRegion() } } -#define ENDIAN_TEST(endian, type, size) \ - do { \ - QCOMPARE(qTo ## endian ## Endian( \ - (type ## size)(inNativeEndian.data ## size)), \ - (type ## size)(in ## endian ## Endian.data.data ## size)); \ - \ - RawTestData test; \ - qTo ## endian ## Endian( \ - (type ## size)(inNativeEndian.data ## size), \ - test.rawData + offsetof(TestData, data ## size)); \ - QCOMPARE(test.data.data ## size, in ## endian ## Endian.data.data ## size ); \ - } while (false) \ +#define ENDIAN_TEST(endian, Type, Data) \ + do { \ + QCOMPARE(qTo ## endian ## Endian( \ + (Type)(inNativeEndian.Data)), \ + (Type)(in ## endian ## Endian.data.Data)); \ + \ + RawTestData test; \ + qTo ## endian ## Endian( \ + (Type)(inNativeEndian.Data), \ + test.rawData + offsetof(TestData, Data)); \ + QCOMPARE(test.data.Data, in ## endian ## Endian.data.Data ); \ + } while (false) \ /**/ void tst_QtEndian::toBigEndian() @@ -360,32 +373,108 @@ void tst_QtEndian::endianIntegers() #endif } -void tst_QtEndian::endianBitfields() +template<template<typename... Accessors> typename Union, template<int, int, typename> typename Member> +void testBitfieldUnion() +{ + using upper = Member<21, 11, uint>; + using lower = Member<10, 11, uint>; + using bottom = Member<0, 10, int>; + using all = Member<0, 32, uint>; + + using UnionType = Union<upper, lower, bottom, all>; + UnionType u; + + u.template set<upper>(200); + QCOMPARE(u.template get<upper>(), 200U); + u.template set<lower>(1000); + u.template set<bottom>(-8); + QCOMPARE(u.template get<lower>(), 1000U); + QCOMPARE(u.template get<upper>(), 200U); + + u.template set<lower>(u.template get<lower>() + u.template get<upper>()); + QCOMPARE(u.template get<upper>(), 200U); + QCOMPARE(u.template get<lower>(), 1200U); + + u.template set<upper>(65536 + 7); + u.template set<lower>(65535); + QCOMPARE(u.template get<lower>(), 65535U & ((1<<11) - 1)); + QCOMPARE(u.template get<upper>(), 7U); + + QCOMPARE(u.template get<bottom>(), -8); + + UnionType u2(QSpecialIntegerBitfieldZero); + QCOMPARE(u2.data(), 0U); + + u2.template set<all>(std::numeric_limits<uint>::max()); + QCOMPARE(u2.template get<all>(), std::numeric_limits<uint>::max()); + + u2.template set<all>(453); + QCOMPARE(u2.template get<all>(), 453U); + + u2.template set<all>(0); + QCOMPARE(u2.template get<all>(), 0U); + + UnionType u3(42U); + QCOMPARE(u3.data(), 42U); + + using BEUintAccessor = QSpecialIntegerAccessor<QBigEndianStorageType<uint>, 21, 11>; + using LEUintAccessor = QSpecialIntegerAccessor<QLittleEndianStorageType<uint>, 21, 11>; + using BEIntAccessor = QSpecialIntegerAccessor<QBigEndianStorageType<int>, 0, 10>; + using LEIntAccessor = QSpecialIntegerAccessor<QLittleEndianStorageType<int>, 0, 10>; + + if constexpr (std::is_same_v<BEUintAccessor, upper>) { + QCOMPARE(u.template get<BEUintAccessor>(), 7U); + } else if constexpr (std::is_same_v<LEUintAccessor, upper>) { + QCOMPARE(u.template get<LEUintAccessor>(), 7U); + } else if constexpr (std::is_same_v<BEIntAccessor, bottom>) { + QCOMPARE(u.template get<BEIntAccessor>(), -8); + } else if constexpr (std::is_same_v<LEIntAccessor, bottom>) { + QCOMPARE(u.template get<LEIntAccessor>(), -8); + } else { + QFAIL("none of the manually defined accessors match"); + } +} + +void tst_QtEndian::endianBitfieldUnions_data() +{ + QTest::addColumn<QSysInfo::Endian>("byteOrder"); + QTest::addColumn<Signedness>("signedness"); + + QTest::addRow("little endian unsigned") << QSysInfo::LittleEndian << Unsigned; + QTest::addRow("little endian signed") << QSysInfo::LittleEndian << Signed; + QTest::addRow("big endian unsigned") << QSysInfo::BigEndian << Unsigned; + QTest::addRow("big endian signed") << QSysInfo::BigEndian << Signed; +} + +void tst_QtEndian::endianBitfieldUnions() { - union { - quint32_be_bitfield<21, 11> upper; - quint32_be_bitfield<10, 11> lower; - qint32_be_bitfield<0, 10> bottom; - } u; - - u.upper = 200; - QCOMPARE(u.upper, 200U); - u.lower = 1000; - u.bottom = -8; - QCOMPARE(u.lower, 1000U); - QCOMPARE(u.upper, 200U); - - u.lower += u.upper; - QCOMPARE(u.upper, 200U); - QCOMPARE(u.lower, 1200U); - - u.upper = 65536 + 7; - u.lower = 65535; - QCOMPARE(u.lower, 65535U & ((1<<11) - 1)); - QCOMPARE(u.upper, 7U); - - QCOMPARE(u.bottom, -8); + QFETCH(QSysInfo::Endian, byteOrder); + QFETCH(Signedness, signedness); + + switch (byteOrder) { + case QSysInfo::LittleEndian: + switch (signedness) { + case Unsigned: + testBitfieldUnion<quint32_le_bitfield_union, quint32_le_bitfield_member>(); + return; + case Signed: + testBitfieldUnion<qint32_le_bitfield_union, qint32_le_bitfield_member>(); + return; + } + Q_UNREACHABLE_RETURN(); + case QSysInfo::BigEndian: + switch (signedness) { + case Unsigned: + testBitfieldUnion<quint32_be_bitfield_union, quint32_be_bitfield_member>(); + return; + case Signed: + testBitfieldUnion<qint32_be_bitfield_union, qint32_be_bitfield_member>(); + return; + } + Q_UNREACHABLE_RETURN(); + } } + QTEST_MAIN(tst_QtEndian) #include "tst_qtendian.moc" diff --git a/tests/auto/corelib/global/qwinregistry/CMakeLists.txt b/tests/auto/corelib/global/qwinregistry/CMakeLists.txt deleted file mode 100644 index 95d591a125..0000000000 --- a/tests/auto/corelib/global/qwinregistry/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Generated from qwinregistry.pro. - -##################################################################### -## tst_qwinregistry Test: -##################################################################### - -qt_internal_add_test(tst_qwinregistry - SOURCES - tst_qwinregistry.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate -) diff --git a/tests/auto/corelib/global/qwinregistry/tst_qwinregistry.cpp b/tests/auto/corelib/global/qwinregistry/tst_qwinregistry.cpp deleted file mode 100644 index c73a0a7575..0000000000 --- a/tests/auto/corelib/global/qwinregistry/tst_qwinregistry.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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 <QTest> - -#include <QtCore/qoperatingsystemversion.h> - -#include <QtCore/private/qwinregistry_p.h> - -class tst_QWinRegistry : public QObject -{ - Q_OBJECT - -public Q_SLOTS: - void initTestCase(); - -private Q_SLOTS: - void values(); -}; - -void tst_QWinRegistry::initTestCase() -{ - if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows10) - QSKIP("This test requires registry values present in Windows 10"); -} - -void tst_QWinRegistry::values() -{ - QWinRegistryKey key(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"); - QVERIFY(key.isValid()); - QVERIFY(!key.stringValue(L"ProductName").isEmpty()); - QVERIFY(key.stringValue(L"NonExistingKey").isEmpty()); - auto majorVersion = key.dwordValue(L"CurrentMajorVersionNumber"); - QVERIFY(majorVersion.second); - QVERIFY(majorVersion.first > 0); - auto nonExistingValue = key.dwordValue(L"NonExistingKey"); - QVERIFY(!nonExistingValue.second); - QCOMPARE(nonExistingValue.first, 0u); -} - -QTEST_APPLESS_MAIN(tst_QWinRegistry); - -#include "tst_qwinregistry.moc" diff --git a/tests/auto/corelib/global/qxp/CMakeLists.txt b/tests/auto/corelib/global/qxp/CMakeLists.txt new file mode 100644 index 0000000000..2178f446db --- /dev/null +++ b/tests/auto/corelib/global/qxp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(function_ref) +add_subdirectory(is_virtual_base_of) diff --git a/tests/auto/corelib/global/qxp/function_ref/CMakeLists.txt b/tests/auto/corelib/global/qxp/function_ref/CMakeLists.txt new file mode 100644 index 0000000000..351fe24b22 --- /dev/null +++ b/tests/auto/corelib/global/qxp/function_ref/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qxp_function_ref LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qxp_function_ref + EXCEPTIONS + SOURCES + tst_qxp_function_ref.cpp + LIBRARIES + Qt::Core +) diff --git a/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp b/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp new file mode 100644 index 0000000000..ee50a311ef --- /dev/null +++ b/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp @@ -0,0 +1,281 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtCore/qxpfunctional.h> + +#include <QTest> + +#include <type_traits> + +// checking dependency q20::remove_cvref_t: +#define CHECK(in, out) \ + static_assert(std::is_same_v<q20::remove_cvref_t< in >, out >) +CHECK(int, int); +CHECK(const int, int); +CHECK(int &, int); +CHECK(const int &, int); +CHECK(int &&, int); +CHECK(const int &&, int); +CHECK(int *, int *); +CHECK(const int *, const int *); +CHECK(int[4], int[4]); +CHECK(const int (&)[4], int[4]); +#undef CHECK + +template <typename T> constexpr inline bool +is_noexcept_function_ref_helper_v = false; +template <typename R, typename...Args> constexpr inline bool +is_noexcept_function_ref_helper_v<qxp::function_ref<R(Args...) noexcept(true)>> = true; +template <typename R, typename...Args> constexpr inline bool +is_noexcept_function_ref_helper_v<qxp::function_ref<R(Args...) const noexcept(true)>> = true; + +template <typename T> constexpr inline bool +is_noexcept_function_ref_v = is_noexcept_function_ref_helper_v<q20::remove_cvref_t<T>>; + +class tst_qxp_function_ref : public QObject +{ + Q_OBJECT +public: + using QObject::QObject; + +private Q_SLOTS: + void basics(); + void constOverloads(); + void constExpr(); + void voidReturning(); + void ctad(); +}; + +void tst_qxp_function_ref::basics() +{ + static_assert(std::is_trivially_copyable_v<qxp::function_ref<int(int)>>); + static_assert(std::is_trivially_copyable_v<qxp::function_ref<int()>>); + static_assert(std::is_trivially_copyable_v<qxp::function_ref<void()>>); + + { + Q_CONSTINIT static int invoked = 0; + auto lambda = [](int i) noexcept { ++invoked; return i; }; + const qxp::function_ref<int(int)> f = lambda; + QCOMPARE(invoked, 0); + QCOMPARE(f(42), 42); + QCOMPARE(invoked, 1); + + const int fourtyTwo = 42; + + const qxp::function_ref<int(int) noexcept> f2 = std::move(lambda); + QCOMPARE(invoked, 1); + QCOMPARE(f2(fourtyTwo), 42); + QCOMPARE(invoked, 2); + + int (*fpr)(int) = lambda; + + const qxp::function_ref f3 = fpr; + static_assert(!is_noexcept_function_ref_v<decltype(f3)>); + QCOMPARE(invoked, 2); + QCOMPARE(f3(42), 42); + QCOMPARE(invoked, 3); + + int (*fpr2)(int) noexcept = lambda; + + const qxp::function_ref f4 = fpr2; + static_assert(is_noexcept_function_ref_v<decltype(f4)>); + QCOMPARE(invoked, 3); + QCOMPARE(f4(42), 42); + QCOMPARE(invoked, 4); + } + { + Q_CONSTINIT static int invoked = 0; + auto lambda = [] { ++invoked; return 42; }; + const qxp::function_ref<int()> f = lambda; + QCOMPARE(invoked, 0); + QCOMPARE(f(), 42); + QCOMPARE(invoked, 1); + + const qxp::function_ref<int()> f2 = std::move(lambda); + QCOMPARE(invoked, 1); + QCOMPARE(f2(), 42); + QCOMPARE(invoked, 2); + + int (*fpr)() = lambda; + + const qxp::function_ref f3 = fpr; + static_assert(!is_noexcept_function_ref_v<decltype(f3)>); + QCOMPARE(invoked, 2); + QCOMPARE(f3(), 42); + QCOMPARE(invoked, 3); + } + { + Q_CONSTINIT static int invoked = 0; + auto lambda = [] { ++invoked; }; + const qxp::function_ref<void()> f = lambda; + QCOMPARE(invoked, 0); + f(); + QCOMPARE(invoked, 1); + + const qxp::function_ref<void()> f2 = std::move(lambda); + QCOMPARE(invoked, 1); + f2(); + QCOMPARE(invoked, 2); + + void (*fpr)() = lambda; + + const qxp::function_ref f3 = fpr; + QCOMPARE(invoked, 2); + f3(); + QCOMPARE(invoked, 3); + } +} + +void tst_qxp_function_ref::constOverloads() +{ + auto func_c = [](qxp::function_ref<int() const> callable) + { + return callable(); + }; + auto func_m = [](qxp::function_ref<int() /*mutable*/> callable) + { + return callable(); + }; + + struct S + { + int operator()() { return 1; } + int operator()() const { return 2; } + }; + S s; + QCOMPARE(func_c(s), 2); + QCOMPARE(func_m(s), 1); + const S cs; + QCOMPARE(func_c(cs), 2); +#if 0 + // this should not compile (and doesn't, but currently fails with an error in the impl, + // not by failing a constructor constaint → spec issue?). + QCOMPARE(func_m(cs), 2); +#endif +} + +void tst_qxp_function_ref::constExpr() +{ + Q_CONSTINIT static int invoked = 0; + { + Q_CONSTINIT static auto lambda = [] (int i) { ++invoked; return i; }; + // the function object constructor is constexpr, so this should be constinit: + Q_CONSTINIT static qxp::function_ref<int(int)> f = lambda; + + QCOMPARE(invoked, 0); + QCOMPARE(f(15), 15); + QCOMPARE(invoked, 1); + } + { + constexpr static auto lambda = [] (int i) { ++invoked; return i; }; + // the function object constructor is constexpr, so this should be constinit: + Q_CONSTINIT static qxp::function_ref<int(int) const> f = lambda; + + QCOMPARE(invoked, 1); + QCOMPARE(f(51), 51); + QCOMPARE(invoked, 2); + +#if 0 // ### should this work?: + Q_CONSTINIT static qxp::function_ref<int(int)> f2 = lambda; + + QCOMPARE(invoked, 2); + QCOMPARE(f(150), 150); + QCOMPARE(invoked, 3); +#endif + + } +} + +int i_f_i_nx(int i) noexcept { return i; } +void v_f_i_nx(int) noexcept {} +int i_f_v_nx() noexcept { return 42; } +void v_f_v_nx() noexcept {} + +int i_f_i_ex(int i) { return i; } +void v_f_i_ex(int) {} +int i_f_v_ex() { return 42; } +void v_f_v_ex() {} + +void tst_qxp_function_ref::voidReturning() +{ + // check that "casting" int to void returns works: + + using Fi = qxp::function_ref<void(int)>; + using Fv = qxp::function_ref<void()>; + + { + Fi fi = i_f_i_nx; + fi(42); + Fv fv = i_f_v_nx; + fv(); + } + + { + Fi fi = i_f_i_ex; + fi(42); + Fv fv = i_f_v_ex; + fv(); + } + + // now with lambdas + + bool ok = false; // prevent lambdas from decaying to function pointers + { + auto lambda1 = [&](int i) noexcept { return i + int(ok); }; + Fi fi = lambda1; + fi(42); + auto lambda2 = [&]() noexcept { return int(ok); }; + Fv fv = lambda2; + fv(); + } + + { + auto lambda1 = [&](int i) { return i + int(ok); }; + Fi fi = lambda1; + fi(42); + auto lambda2 = [&]() { return int(ok); }; + Fv fv = lambda2; + fv(); + } +} + +void tst_qxp_function_ref::ctad() +{ +#define CHECK(fun, sig) \ + do { \ + qxp::function_ref f = fun; \ + static_assert(std::is_same_v<decltype(f), \ + qxp::function_ref<sig>>); \ + qxp::function_ref f2 = &fun; \ + static_assert(std::is_same_v<decltype(f2), \ + qxp::function_ref<sig>>); \ + static_assert(std::is_trivially_copyable_v<decltype(f)>); \ + static_assert(std::is_trivially_copyable_v<decltype(f2)>); \ + } while (false) + + CHECK(i_f_i_nx, int (int) noexcept); + CHECK(v_f_i_nx, void(int) noexcept); + CHECK(i_f_v_nx, int ( ) noexcept); + CHECK(v_f_v_nx, void( ) noexcept); + + CHECK(i_f_i_ex, int (int)); + CHECK(v_f_i_ex, void(int)); + CHECK(i_f_v_ex, int ( )); + CHECK(v_f_v_ex, void( )); + +#undef CHECK + +#if 0 // no deduction guides for the non-function-pointer case, so no CTAD for lambdas + { + auto lambda = [](int i) -> int { return i; }; + qxp::function_ref f = lambda; + static_assert(std::is_same_v<decltype(f), + qxp::function_ref<int(int)>>); + } +#endif +} + + +QTEST_APPLESS_MAIN(tst_qxp_function_ref); + +#include "tst_qxp_function_ref.moc" diff --git a/tests/auto/corelib/global/qxp/is_virtual_base_of/CMakeLists.txt b/tests/auto/corelib/global/qxp/is_virtual_base_of/CMakeLists.txt new file mode 100644 index 0000000000..85a6daab7c --- /dev/null +++ b/tests/auto/corelib/global/qxp/is_virtual_base_of/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qxp_is_virtual_base_of LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qxp_is_virtual_base_of + EXCEPTIONS + SOURCES + tst_is_virtual_base_of.cpp + LIBRARIES + Qt::Core +) + +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90449 +# GCCs < 10 have no way to suppress "inaccessible base" warnings, except by disabling all warnings: +qt_internal_extend_target(tst_qxp_is_virtual_base_of + CONDITION GCC AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10") + COMPILE_OPTIONS -w +) diff --git a/tests/auto/corelib/global/qxp/is_virtual_base_of/tst_is_virtual_base_of.cpp b/tests/auto/corelib/global/qxp/is_virtual_base_of/tst_is_virtual_base_of.cpp new file mode 100644 index 0000000000..e50575f5ec --- /dev/null +++ b/tests/auto/corelib/global/qxp/is_virtual_base_of/tst_is_virtual_base_of.cpp @@ -0,0 +1,102 @@ +// Copyright (C) 2023 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtCore/qxptype_traits.h> + +#include <QTest> + +class tst_qxp_is_virtual_base_of : public QObject +{ + Q_OBJECT +}; + +class Base { +public: + virtual ~Base() {} +}; + +// Only works with classes +static_assert(!qxp::is_virtual_base_of_v<int, int>); +static_assert(!qxp::is_virtual_base_of_v<int, Base>); +static_assert(!qxp::is_virtual_base_of_v<Base, int>); + +// A class isn't a virtual base of itself +static_assert(!qxp::is_virtual_base_of_v<Base, Base>); + +// Non-virtual bases +class NonVirtualDerived : public Base {}; +class NonVirtualPrivateDerived : private Base {}; + +static_assert(!qxp::is_virtual_base_of_v<Base, NonVirtualDerived>); +static_assert(!qxp::is_virtual_base_of_v<Base, NonVirtualPrivateDerived>); + +static_assert(!qxp::is_virtual_base_of_v<NonVirtualPrivateDerived, NonVirtualDerived>); +static_assert(!qxp::is_virtual_base_of_v<NonVirtualDerived, NonVirtualPrivateDerived>); + +static_assert(!qxp::is_virtual_base_of_v<tst_qxp_is_virtual_base_of, QObject>); + +// Virtual bases +class VirtualDerived1 : public virtual Base {}; +class VirtualDerived2 : public virtual Base {}; +class VirtualDerived3 : public VirtualDerived1, public VirtualDerived2 {}; +class VirtualDerived4 : public VirtualDerived3, public virtual Base {}; +class VirtualPrivateDerived : private virtual Base {}; + +static_assert(qxp::is_virtual_base_of_v<Base, VirtualDerived1>); +static_assert(qxp::is_virtual_base_of_v<Base, VirtualDerived2>); +static_assert(qxp::is_virtual_base_of_v<Base, VirtualDerived3>); +static_assert(!qxp::is_virtual_base_of_v<VirtualDerived1, VirtualDerived3>); +static_assert(qxp::is_virtual_base_of_v<Base, VirtualDerived4>); +static_assert(qxp::is_virtual_base_of_v<Base, VirtualPrivateDerived>); + +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Winaccessible-base") +QT_WARNING_DISABLE_CLANG("-Winaccessible-base") +// Ambiguous non-virtual base +class IntermediateDerived : public Base {}; +class AmbiguousBase1 : public IntermediateDerived, public Base {}; +class AmbiguousBase2 : public IntermediateDerived, public virtual Base {}; + +static_assert(!qxp::is_virtual_base_of_v<Base, AmbiguousBase1>); +#ifndef Q_CC_MSVC_ONLY // https://developercommunity.visualstudio.com/t/c-templates-multiple-inheritance-ambiguous-access/185674 +static_assert(!qxp::is_virtual_base_of_v<Base, AmbiguousBase2>); +#endif +QT_WARNING_POP + +// Const +static_assert(!qxp::is_virtual_base_of_v< Base, const NonVirtualDerived>); +static_assert(!qxp::is_virtual_base_of_v<const Base, NonVirtualDerived>); +static_assert(!qxp::is_virtual_base_of_v<const Base, const NonVirtualDerived>); + +static_assert(!qxp::is_virtual_base_of_v< Base, const NonVirtualPrivateDerived>); +static_assert(!qxp::is_virtual_base_of_v<const Base, NonVirtualPrivateDerived>); +static_assert(!qxp::is_virtual_base_of_v<const Base, const NonVirtualPrivateDerived>); + +static_assert(qxp::is_virtual_base_of_v< Base, const VirtualDerived1>); +static_assert(qxp::is_virtual_base_of_v<const Base, VirtualDerived1>); +static_assert(qxp::is_virtual_base_of_v<const Base, const VirtualDerived1>); + +static_assert(qxp::is_virtual_base_of_v< Base, const VirtualDerived2>); +static_assert(qxp::is_virtual_base_of_v<const Base, VirtualDerived2>); +static_assert(qxp::is_virtual_base_of_v<const Base, const VirtualDerived2>); + +static_assert(qxp::is_virtual_base_of_v< Base, const VirtualDerived3>); +static_assert(qxp::is_virtual_base_of_v<const Base, VirtualDerived3>); +static_assert(qxp::is_virtual_base_of_v<const Base, const VirtualDerived3>); + +static_assert(qxp::is_virtual_base_of_v< Base, const VirtualDerived4>); +static_assert(qxp::is_virtual_base_of_v<const Base, VirtualDerived4>); +static_assert(qxp::is_virtual_base_of_v<const Base, const VirtualDerived4>); + +static_assert(qxp::is_virtual_base_of_v< Base, const VirtualDerived4>); +static_assert(qxp::is_virtual_base_of_v<const Base, VirtualDerived4>); +static_assert(qxp::is_virtual_base_of_v<const Base, const VirtualDerived4>); + +static_assert(qxp::is_virtual_base_of_v< Base, const VirtualPrivateDerived>); +static_assert(qxp::is_virtual_base_of_v<const Base, VirtualPrivateDerived>); +static_assert(qxp::is_virtual_base_of_v<const Base, const VirtualPrivateDerived>); + + +QTEST_APPLESS_MAIN(tst_qxp_is_virtual_base_of); + +#include "tst_is_virtual_base_of.moc" |