diff options
Diffstat (limited to 'tests/auto/corelib/tools')
107 files changed, 4034 insertions, 782 deletions
diff --git a/tests/auto/corelib/tools/CMakeLists.txt b/tests/auto/corelib/tools/CMakeLists.txt index 8c7ab96e71..5cca2e2df6 100644 --- a/tests/auto/corelib/tools/CMakeLists.txt +++ b/tests/auto/corelib/tools/CMakeLists.txt @@ -1,7 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from tools.pro. add_subdirectory(qatomicscopedvaluerollback) if(NOT INTEGRITY) add_subdirectory(collections) @@ -18,7 +17,9 @@ add_subdirectory(qduplicatetracker) add_subdirectory(qeasingcurve) add_subdirectory(qexplicitlyshareddatapointer) add_subdirectory(qflatmap) -add_subdirectory(qfreelist) +if(QT_FEATURE_private_tests) + add_subdirectory(qfreelist) +endif() add_subdirectory(qhash) add_subdirectory(qhashfunctions) add_subdirectory(qhashseed) @@ -41,11 +42,14 @@ add_subdirectory(qscopedpointer) add_subdirectory(qscopedvaluerollback) add_subdirectory(qscopeguard) add_subdirectory(qtaggedpointer) +add_subdirectory(qtyperevision) add_subdirectory(qset) add_subdirectory(qsharedpointer) add_subdirectory(qsize) add_subdirectory(qsizef) +add_subdirectory(qspan) add_subdirectory(qstl) +add_subdirectory(quniquehandle) add_subdirectory(qvarlengtharray) add_subdirectory(qversionnumber) add_subdirectory(qtimeline) diff --git a/tests/auto/corelib/tools/collections/CMakeLists.txt b/tests/auto/corelib/tools/collections/CMakeLists.txt index 460ef6f3b9..687d88b2e4 100644 --- a/tests/auto/corelib/tools/collections/CMakeLists.txt +++ b/tests/auto/corelib/tools/collections/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from collections.pro. - ##################################################################### ## tst_collections Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_collections LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_collections SOURCES tst_collections.cpp diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp index 23ebf5046a..2fab6cae3a 100644 --- a/tests/auto/corelib/tools/collections/tst_collections.cpp +++ b/tests/auto/corelib/tools/collections/tst_collections.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#undef QT_NO_FOREACH // this file tests Q_FOREACH over containers (centralize in a tst_qforeach?) // test the container forwards #include <QtContainerFwd> @@ -294,8 +295,8 @@ constexpr inline bool has_prepend_v<QVarLengthArray<T,N>> = false; // deprecated void tst_Collections::typeinfo() { - QVERIFY(QTypeInfo<int*>::isPointer); - QVERIFY(!QTypeInfo<int>::isPointer); + QVERIFY(std::is_pointer_v<int*>); + QVERIFY(!std::is_pointer_v<int>); QVERIFY(QTypeInfo<QString>::isComplex); QVERIFY(!QTypeInfo<int>::isComplex); } @@ -529,7 +530,7 @@ void tst_Collections::list() list << "one" << "two" << "one" << "two"; QVERIFY(!list.removeOne("three")); QVERIFY(list.removeOne("two")); - QCOMPARE(list, QList<QString>() << "one" << "one" << "two");; + QCOMPARE(list, QList<QString>() << "one" << "one" << "two"); QVERIFY(list.removeOne("two")); QCOMPARE(list, QList<QString>() << "one" << "one"); QVERIFY(!list.removeOne("two")); @@ -684,7 +685,7 @@ QT_WARNING_POP list.insert(0, "atzero"); QCOMPARE(list.at(0), QString("atzero")); - int listCount = list.count(); + int listCount = list.size(); list.insert(listCount, "atcount"); QCOMPARE(list.at(listCount), QString("atcount")); } @@ -2018,8 +2019,8 @@ void tst_Collections::qstring() s = "ascii"; s += QChar((uchar) 0xb0); QVERIFY(s.toUtf8() != s.toLatin1()); - QCOMPARE(s[s.length()-1].unicode(), (ushort)0xb0); - QCOMPARE(s.left(s.length()-1), QLatin1String("ascii")); + QCOMPARE(s[s.size()-1].unicode(), char16_t(0xb0)); + QCOMPARE(s.left(s.size()-1), QLatin1String("ascii")); QVERIFY(s == QString::fromUtf8(s.toUtf8().constData())); @@ -2071,7 +2072,7 @@ void tst_Collections::qstring() QString str = "Hello"; - QString cstr = QString::fromRawData(str.unicode(), str.length()); + QString cstr = QString::fromRawData(str.unicode(), str.size()); QCOMPARE(str, QLatin1String("Hello")); QCOMPARE(cstr, QLatin1String("Hello")); cstr.clear(); @@ -2693,7 +2694,7 @@ void tst_Collections::vector_stl() QFETCH(QStringList, elements); QList<QString> vector; - for (int i = 0; i < elements.count(); ++i) + for (int i = 0; i < elements.size(); ++i) vector << elements.at(i); #if QT_VERSION < QT_VERSION_CHECK(6,0,0) @@ -2728,7 +2729,7 @@ void tst_Collections::list_stl() QFETCH(QStringList, elements); QList<QString> list; - for (int i = 0; i < elements.count(); ++i) + for (int i = 0; i < elements.size(); ++i) list << elements.at(i); #if QT_VERSION < QT_VERSION_CHECK(6,0,0) @@ -2821,7 +2822,7 @@ void instantiateContainer() container.clear(); container.contains(value); - container.count(); + container.size(); container.empty(); container.isEmpty(); container.size(); @@ -3244,7 +3245,7 @@ template<template<class> class C> void QTBUG13079_collectionInsideCollectionImpl QCOMPARE(nodeList.first().s, QString::fromLatin1("child")); nodeList = nodeList.first().children; - QCOMPARE(nodeList.count(), 0); + QCOMPARE(nodeList.size(), 0); nodeList << QTBUG13079_Node<C>(); } @@ -3269,7 +3270,7 @@ template<template<class, class> class C> void QTBUG13079_collectionInsideCollect QCOMPARE(nodeMap[12].s, QString::fromLatin1("child")); nodeMap = nodeMap[12].children; - QCOMPARE(nodeMap.count(), 0); + QCOMPARE(nodeMap.size(), 0); nodeMap[42] = QTBUG13079_NodeAssoc<C>(); } @@ -3336,7 +3337,7 @@ void tst_Collections::QTBUG13079_collectionInsideCollection() QSet<QTBUG13079_Node<QSet> > nodeSet; nodeSet << QTBUG13079_Node<QSet>(); nodeSet = nodeSet.begin()->children; - QCOMPARE(nodeSet.count(), 0); + QCOMPARE(nodeSet.size(), 0); } QTBUG13079_collectionInsideCollectionAssocImpl<QMap>(); @@ -3358,7 +3359,7 @@ template<class Container> void foreach_test_arrays(const Container &container) set << val; i++; } - QCOMPARE(set.count(), container.count()); + QCOMPARE(set.size(), container.size()); //modify the container while iterating. Container c2 = container; @@ -3395,9 +3396,9 @@ void tst_Collections::foreach_2() varl2 << i; varl3 << i; } - QCOMPARE(varl1.count(), intlist.count()); - QCOMPARE(varl2.count(), intlist.count()); - QCOMPARE(varl3.count(), intlist.count()); + QCOMPARE(varl1.size(), intlist.size()); + QCOMPARE(varl2.size(), intlist.size()); + QCOMPARE(varl3.size(), intlist.size()); QVarLengthArray<QString> varl4; QVarLengthArray<QString, 3> varl5; @@ -3407,9 +3408,9 @@ void tst_Collections::foreach_2() varl5 << str; varl6 << str; } - QCOMPARE(varl4.count(), strlist.count()); - QCOMPARE(varl5.count(), strlist.count()); - QCOMPARE(varl6.count(), strlist.count()); + QCOMPARE(varl4.size(), strlist.size()); + QCOMPARE(varl5.size(), strlist.size()); + QCOMPARE(varl6.size(), strlist.size()); } struct IntOrString @@ -3439,8 +3440,8 @@ template<class Container> void insert_remove_loop_impl() t.insert(t.begin() + 2, T(IntOrString(7))); t.insert(t.begin() + 5, 3, T(IntOrString(8))); int expect1[] = { 4 , 1 , 7, 5 , 5 , 8, 8, 8, 6, 5, 2 , 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect1)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { + QCOMPARE(size_t(t.size()), sizeof(expect1)/sizeof(int)); + for (int i = 0; i < t.size(); i++) { QCOMPARE(t[i], T(IntOrString(expect1[i]))); } @@ -3454,8 +3455,8 @@ template<class Container> void insert_remove_loop_impl() t.remove(7); t.remove(2, 3); int expect2[] = { 4 , 1 , 9, 8, 6, 5, 2 , 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect2)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { + QCOMPARE(size_t(t.size()), sizeof(expect2)/sizeof(int)); + for (int i = 0; i < t.size(); i++) { QCOMPARE(t[i], T(IntOrString(expect2[i]))); } @@ -3467,16 +3468,16 @@ template<class Container> void insert_remove_loop_impl() } int expect3[] = { 1 , 9, 5, 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect3)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { + QCOMPARE(size_t(t.size()), sizeof(expect3)/sizeof(int)); + for (int i = 0; i < t.size(); i++) { QCOMPARE(t[i], T(IntOrString(expect3[i]))); } t.erase(t.begin() + 1, t.end() - 1); int expect4[] = { 1 , 3 }; - QCOMPARE(size_t(t.count()), sizeof(expect4)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { + QCOMPARE(size_t(t.size()), sizeof(expect4)/sizeof(int)); + for (int i = 0; i < t.size(); i++) { QCOMPARE(t[i], T(IntOrString(expect4[i]))); } @@ -3493,8 +3494,8 @@ template<class Container> void insert_remove_loop_impl() int expect5[] = { 1, 1, 2, 3*3, 3, 3*3+1, 10, 11*11, 11, 11*11+1, 12 , 13*13, 13, 13*13+1, 14, 15*15, 15, 15*15+1, 16 , 17*17, 17, 17*17+1 ,18 , 19*19, 19, 19*19+1, 20, 21*21, 21, 21*21+1 }; - QCOMPARE(size_t(t.count()), sizeof(expect5)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { + QCOMPARE(size_t(t.size()), sizeof(expect5)/sizeof(int)); + for (int i = 0; i < t.size(); i++) { QCOMPARE(t[i], T(IntOrString(expect5[i]))); } @@ -3504,8 +3505,8 @@ template<class Container> void insert_remove_loop_impl() t.insert(2, 4, T(IntOrString(7))); int expect6[] = { 1, 2, 7, 7, 7, 7, 9, 9, 9, 9, 3, 4 }; - QCOMPARE(size_t(t.count()), sizeof(expect6)/sizeof(int)); - for (int i = 0; i < t.count(); i++) { + QCOMPARE(size_t(t.size()), sizeof(expect6)/sizeof(int)); + for (int i = 0; i < t.size(); i++) { QCOMPARE(t[i], T(IntOrString(expect6[i]))); } diff --git a/tests/auto/corelib/tools/containerapisymmetry/CMakeLists.txt b/tests/auto/corelib/tools/containerapisymmetry/CMakeLists.txt index 16ffca60d0..0ae1092043 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/CMakeLists.txt +++ b/tests/auto/corelib/tools/containerapisymmetry/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from containerapisymmetry.pro. - ##################################################################### ## tst_containerapisymmetry Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_containerapisymmetry LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_containerapisymmetry SOURCES tst_containerapisymmetry.cpp diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index 60023e1bf2..5eb9dbfa36 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -14,7 +14,6 @@ #include <algorithm> #include <functional> -#include <vector> // for reference #include <iostream> #include <list> #include <set> @@ -23,10 +22,7 @@ #include <forward_list> #include <unordered_set> #include <unordered_map> - -#if defined(__cpp_lib_erase_if) && __cpp_lib_erase_if >= 202002L -# define STDLIB_HAS_UNIFORM_ERASURE -#endif +#include <q20vector.h> // For reference QT_BEGIN_NAMESPACE std::ostream &operator<<(std::ostream &os, const QChar &c) @@ -333,6 +329,38 @@ private Q_SLOTS: private: template <typename Container> + void copesWithValueTypesWithConstMembers_impl(); + + struct ConstMember { + #ifndef __cpp_aggregate_paren_init // also check that we can emplace aggregates (C++20 only) + explicit ConstMember(int n) : n(n) {} + #endif + const int n; + + friend bool operator==(const ConstMember &lhs, const ConstMember &rhs) noexcept + { return lhs.n == rhs.n; } + friend bool operator!=(const ConstMember &lhs, const ConstMember &rhs) noexcept + { return !(lhs == rhs); } + }; + +private Q_SLOTS: + void copesWithValueTypesWithConstMembers_std_vector() { copesWithValueTypesWithConstMembers_impl<std::vector<ConstMember>>(); } + void copesWithValueTypesWithConstMembers_QVarLengthArray() { copesWithValueTypesWithConstMembers_impl<QVarLengthArray<ConstMember, 2>>(); } + +private: + template <typename Container> + void assign_impl() const; + +private Q_SLOTS: + void assign_std_vector() { assign_impl<std::vector<int>>(); }; + void assign_std_string() { assign_impl<std::string>(); } + void assign_QVarLengthArray() { assign_impl<QVarLengthArray<int, 4>>(); }; + void assign_QList() { assign_impl<QList<int>>(); } + void assign_QByteArray() { assign_impl<QByteArray>(); } + void assign_QString() { assign_impl<QString>(); } + +private: + template <typename Container> void front_back_impl() const; private Q_SLOTS: @@ -354,32 +382,44 @@ private: template <typename Container> void erase_if_associative_impl() const; + template <typename Container> + void member_erase_impl() const; + + template <typename Container> + void member_erase_associative_impl() const; + + template <typename Container> + void member_erase_set_impl() const; + private Q_SLOTS: void erase_QList() { erase_impl<QList<int>>(); } void erase_QVarLengthArray() { erase_impl<QVarLengthArray<int>>(); } void erase_QString() { erase_impl<QString>(); } void erase_QByteArray() { erase_impl<QByteArray>(); } - void erase_std_vector() { -#ifdef STDLIB_HAS_UNIFORM_ERASURE - erase_impl<std::vector<int>>(); -#endif - } + void erase_std_vector() { erase_impl<std::vector<int>>(); } void erase_if_QList() { erase_if_impl<QList<int>>(); } void erase_if_QVarLengthArray() { erase_if_impl<QVarLengthArray<int>>(); } void erase_if_QSet() { erase_if_impl<QSet<int>>(); } void erase_if_QString() { erase_if_impl<QString>(); } void erase_if_QByteArray() { erase_if_impl<QByteArray>(); } - void erase_if_std_vector() { -#ifdef STDLIB_HAS_UNIFORM_ERASURE - erase_if_impl<std::vector<int>>(); -#endif - } + void erase_if_std_vector() { erase_if_impl<std::vector<int>>(); } void erase_if_QMap() { erase_if_associative_impl<QMap<int, int>>(); } void erase_if_QMultiMap() {erase_if_associative_impl<QMultiMap<int, int>>(); } void erase_if_QHash() { erase_if_associative_impl<QHash<int, int>>(); } void erase_if_QMultiHash() { erase_if_associative_impl<QMultiHash<int, int>>(); } + void member_erase_QList() { member_erase_impl<QList<int>>(); } + void member_erase_QVarLengthArray() { member_erase_impl<QVarLengthArray<int>>(); } + void member_erase_QString() { member_erase_impl<QString>(); } + void member_erase_QByteArray() { member_erase_impl<QByteArray>(); } + void member_erase_QSet() { member_erase_set_impl<QSet<int>>(); } + + void member_erase_QMap() { member_erase_associative_impl<QMap<int, int>>(); } + void member_erase_QMultiMap() {member_erase_associative_impl<QMultiMap<int, int>>(); } + void member_erase_QHash() { member_erase_associative_impl<QHash<int, int>>(); } + void member_erase_QMultiHash() { member_erase_associative_impl<QMultiHash<int, int>>(); } + private: template <typename Container> void keyValueRange_impl() const; @@ -690,7 +730,8 @@ Container make(int size) Container c; c.reserve(size); using V = typename Container::value_type; - std::generate_n(std::inserter(c, c.end()), size, [i = 1]() mutable { return V(i++); }); + int i = 0; + std::generate_n(std::inserter(c, c.end()), size, [&i] { return V(++i); }); return c; } @@ -723,7 +764,7 @@ void tst_ContainerApiSymmetry::resize_impl() const auto c = make<Container>(3); QCOMPARE(c.size(), S(3)); c.resize(4, V(5)); - QCOMPARE(c.size(), S(4)); + QCOMPARE(std::size(c), S(4)); QCOMPARE(c.back(), V(5)); // ctor/resize symmetry: @@ -739,21 +780,186 @@ void tst_ContainerApiSymmetry::resize_impl() const } } +template <typename T> +[[maybe_unused]] +constexpr bool is_vector_v = false; +template <typename...Args> +constexpr bool is_vector_v<std::vector<Args...>> = true; + +template <typename Container, typename Value> +void wrap_resize(Container &c, typename Container::size_type n, const Value &v) +{ +#ifdef __GLIBCXX__ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83981 + if constexpr (is_vector_v<Container>) { + while (c.size() < n) + c.push_back(v); + } else +#endif + { + c.resize(n, v); + } +} + +template <typename Container> +void tst_ContainerApiSymmetry::copesWithValueTypesWithConstMembers_impl() +{ + // The problem: + // + // using V = ConstMember; + // V v{42}; + // assert(v.n == 42); // OK + // new (&v) V{24}; + // assert(v.n == 24); // UB in C++17: v.n could still be 42 (C++17 [basic.life]/8) + // // OK in C++20 (C++20 [basic.life]/8) + // assert(std::launder(&v)->n == 24); // OK + // assert(v.n == 24); // _still_ UB! + // + // Containers: + // - must not expose this problem + // - must compile in the first place, even though V + // - is not assignable + // - is not default-constructible + + using S = typename Container::size_type; + using V = typename Container::value_type; + + Container c; + // the following are all functions that by rights should not require the type to be + // - default-constructible + // - assignable + // make sure they work + c.reserve(S(5)); + c.shrink_to_fit(); + wrap_resize(c, 1, V(42)); + QCOMPARE(c[0], V(42)); + wrap_resize(c, 2, V(48)); + QCOMPARE(c[0], V(42)); + QCOMPARE(c[1], V(48)); + c.clear(); + c.emplace_back(24); + QCOMPARE(c.front(), V(24)); + c.push_back(V(41)); + QCOMPARE(c.back(), V(41)); + { + const auto v142 = V(142); + c.push_back(v142); + } + QCOMPARE(c.size(), S(3)); + QCOMPARE(c[0], V(24)); + QCOMPARE(c[1], V(41)); + QCOMPARE(c[2], V(142)); +} + template <typename Container> +void tst_ContainerApiSymmetry::assign_impl() const +{ +#define CHECK(Arr, ComparisonData, Sz_n, Sz_e) \ + QCOMPARE(Sz_n, Sz_e); \ + for (const auto &e : Arr) \ + QCOMPARE(e, ComparisonData) \ + /*end*/ +#define RET_CHECK(...) \ + do { \ + if constexpr (std::is_void_v<decltype( __VA_ARGS__ )>) { \ + /* e.g. std::vector */ \ + __VA_ARGS__ ; \ + } else { \ + /* e.g. std::basic_string */ \ + auto &&r = __VA_ARGS__ ; \ + QCOMPARE_EQ(&r, &c); \ + } \ + } while (false) \ + /* end */ + using V = typename Container::value_type; + using S = typename Container::size_type; + auto tData = V(65); + { + // fill version + auto c = make<Container>(4); + const S oldCapacity = c.capacity(); + RET_CHECK(c.assign(4, tData)); + CHECK(c, tData, c.size(), S(4)); + QCOMPARE_EQ(c.capacity(), oldCapacity); + + tData = V(66); + c.assign(8, tData); // may reallocate + CHECK(c, tData, c.size(), S(8)); + + const S grownCapacity = c.capacity(); + c.assign(0, tData); + CHECK(c, tData, c.size(), S(0)); + QCOMPARE_EQ(c.capacity(), grownCapacity); + } + { + // range version for non input iterator + auto c = make<Container>(4); + auto iter = make<Container>(1); + + iter.assign(8, tData); + RET_CHECK(c.assign(iter.begin(), iter.end())); // may reallocate + CHECK(c, tData, c.size(), S(8)); + + const S oldCapacity = c.capacity(); + c.assign(iter.begin(), iter.begin()); + CHECK(c, tData, c.size(), S(0)); + QCOMPARE_EQ(c.capacity(), oldCapacity); + } + { + // range version for input iterator + auto c = make<Container>(4); + const S oldCapacity = c.capacity(); + + std::stringstream ss; + ss << tData << ' ' << tData << ' '; + RET_CHECK(c.assign(std::istream_iterator<V>{ss}, std::istream_iterator<V>{})); + CHECK(c, tData, c.size(), S(2)); + QCOMPARE_EQ(c.capacity(), oldCapacity); + + ss.str(""); + ss.clear(); + tData = V(66); + ss << tData << ' ' << tData << ' ' << tData << ' ' << tData << ' '; + c.assign(std::istream_iterator<V>{ss}, std::istream_iterator<V>{}); + CHECK(c, tData, c.size(), S(4)); + QCOMPARE_EQ(c.capacity(), oldCapacity); + + ss.str(""); + ss.clear(); + tData = V(67); + ss << tData << ' ' << tData << ' ' << tData << ' ' << tData << ' ' + << tData << ' ' << tData << ' ' << tData << ' '; + c.assign(std::istream_iterator<V>{ss}, std::istream_iterator<V>{}); // may reallocate + CHECK(c, tData, c.size(), S(7)); + } + { + // initializer-list version + auto c = make<Container>(4); + const S oldCapacity = c.capacity(); + std::initializer_list<V> list = {tData, tData, tData}; + RET_CHECK(c.assign(list)); + CHECK(c, tData, c.size(), S(3)); + QCOMPARE_EQ(c.capacity(), oldCapacity); + } + +#undef RET_CHECK +#undef CHECK +} + +template<typename Container> void tst_ContainerApiSymmetry::front_back_impl() const { using V = typename Container::value_type; auto c1 = make<Container>(1); QCOMPARE(clean(c1.front()), V(1)); QCOMPARE(clean(c1.back()), V(1)); - QCOMPARE(clean(qAsConst(c1).front()), V(1)); - QCOMPARE(clean(qAsConst(c1).back()), V(1)); + QCOMPARE(clean(std::as_const(c1).front()), V(1)); + QCOMPARE(clean(std::as_const(c1).back()), V(1)); auto c2 = make<Container>(2); QCOMPARE(clean(c2.front()), V(1)); QCOMPARE(clean(c2.back()), V(2)); - QCOMPARE(clean(qAsConst(c2).front()), V(1)); - QCOMPARE(clean(qAsConst(c2).back()), V(2)); + QCOMPARE(clean(std::as_const(c2).front()), V(1)); + QCOMPARE(clean(std::as_const(c2).back()), V(2)); } namespace { @@ -772,6 +978,7 @@ void tst_ContainerApiSymmetry::erase_impl() const auto c = make<Container>(7); // {1, 2, 3, 4, 5, 6, 7} QCOMPARE(c.size(), S(7)); + using q20::erase; // For std::vector auto result = erase(c, V(1)); QCOMPARE(result, S(1)); QCOMPARE(c.size(), S(6)); @@ -797,7 +1004,10 @@ void tst_ContainerApiSymmetry::erase_if_impl() const oldSize = c.size(); count = 0; - auto result = erase_if(c, [&](V i) { ++count; return Conv::toInt(i) % 2 == 0; }); + + using q20::erase_if; // For std::vector + + S result = erase_if(c, [&](V i) { ++count; return Conv::toInt(i) % 2 == 0; }); QCOMPARE(result, S(3)); QCOMPARE(c.size(), S(4)); QCOMPARE(count, oldSize); @@ -874,6 +1084,65 @@ void tst_ContainerApiSymmetry::erase_if_associative_impl() const } template <typename Container> +void tst_ContainerApiSymmetry::member_erase_impl() const +{ + using S = typename Container::size_type; + using V = typename Container::value_type; + const S size = 7; + auto c = make<Container>(size); // {1, 2, 3, 4, 5, 6, 7} + QCOMPARE(c.size(), size); + + auto copy = c; + // Container::erase() returns an iterator, not const_iterator + auto it = c.erase(c.cbegin(), c.cbegin()); + static_assert(std::is_same_v<decltype(it), typename Container::iterator>); + QCOMPARE(c.size(), size); + const V newVal{100}; + QCOMPARE_NE(*it, newVal); + *it = newVal; + QCOMPARE(it, c.cbegin()); + QCOMPARE(*c.cbegin(), newVal); + + QCOMPARE(std::find(copy.cbegin(), copy.cend(), newVal), copy.cend()); +} + +template <typename Container> +void tst_ContainerApiSymmetry::member_erase_associative_impl() const +{ + using S = typename Container::size_type; + using V = typename Container::mapped_type; + + const S size = 20; + auto c = makeAssociative<Container>(size); + QCOMPARE(c.size(), size); + + // Verify Container::erase() returns iterator, not const_iterator + auto it = c.erase(c.cbegin()); + static_assert(std::is_same_v<decltype(it), typename Container::iterator>); + QCOMPARE(c.size(), size - 1); + QCOMPARE(it, c.cbegin()); + const auto current = it.value(); + it.value() = current + V(5); + QCOMPARE(c.cbegin().value(),current + V(5)); +} + +template <typename Container> +void tst_ContainerApiSymmetry::member_erase_set_impl() const +{ + using S = typename Container::size_type; + + const S size = 20; + auto c = make<Container>(size); + QCOMPARE(c.size(), size); + + // Verify Container::erase() returns iterator, not const_iterator + auto it = c.erase(c.cbegin()); + static_assert(std::is_same_v<decltype(it), typename Container::iterator>); + QCOMPARE(c.size(), size - 1); + QCOMPARE(it, c.cbegin()); +} + +template <typename Container> void tst_ContainerApiSymmetry::keyValueRange_impl() const { constexpr int COUNT = 20; diff --git a/tests/auto/corelib/tools/qalgorithms/CMakeLists.txt b/tests/auto/corelib/tools/qalgorithms/CMakeLists.txt index 4615b8629c..9e87144a4c 100644 --- a/tests/auto/corelib/tools/qalgorithms/CMakeLists.txt +++ b/tests/auto/corelib/tools/qalgorithms/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qalgorithms.pro. - ##################################################################### ## tst_qalgorithms Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qalgorithms LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qalgorithms SOURCES tst_qalgorithms.cpp diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp index 4a06306e31..8d68a7a270 100644 --- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp +++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../../../../../src/corelib/tools/qalgorithms.h" #include <QTest> @@ -70,6 +70,18 @@ private: void countLeading_impl(); }; +template <typename T> struct PrintIfFailed +{ + T value; + PrintIfFailed(T v) : value(v) {} + ~PrintIfFailed() + { + if (!QTest::currentTestFailed()) + return; + qWarning() << "Original value was" << Qt::hex << Qt::showbase << T(value); + } +}; + void tst_QAlgorithms::swap() { { @@ -249,23 +261,26 @@ void tst_QAlgorithms::popCount_data_impl(size_t sizeof_T_Int) const uint bits = bitsSetInByte(byte); const quint64 value = static_cast<quint64>(byte); const quint64 input = value << ((i % sizeof_T_Int) * 8U); - QTest::addRow("0x%016llx", input) << input << bits; + QTest::addRow("%u-bits", i) << input << bits; } // and some random ones: - if (sizeof_T_Int >= 8) + if (sizeof_T_Int >= 8) { for (size_t i = 0; i < 1000; ++i) { const quint64 input = QRandomGenerator::global()->generate64(); - QTest::addRow("0x%016llx", input) << input << bitsSetInInt64(input); + QTest::addRow("random-%zu", i) << input << bitsSetInInt64(input); } - else if (sizeof_T_Int >= 2) - for (size_t i = 0; i < 1000 ; ++i) { - const quint32 input = QRandomGenerator::global()->generate(); - if (sizeof_T_Int >= 4) - QTest::addRow("0x%08x", input) << quint64(input) << bitsSetInInt(input); - else - QTest::addRow("0x%04x", quint16(input & 0xFFFF)) << quint64(input & 0xFFFF) << bitsSetInShort(input & 0xFFFF); + } else if (sizeof_T_Int >= 2) { + for (size_t i = 0; i < 1000 ; ++i) { + const quint32 input = QRandomGenerator::global()->generate(); + if (sizeof_T_Int >= 4) { + QTest::addRow("random-%zu", i) << quint64(input) << bitsSetInInt(input); + } else { + QTest::addRow("random-%zu", i) + << quint64(input & 0xFFFF) << bitsSetInShort(input & 0xFFFF); } + } + } } template <typename T_Int> @@ -275,22 +290,23 @@ void tst_QAlgorithms::popCount_impl() QFETCH(uint, expected); const T_Int value = static_cast<T_Int>(input); - + PrintIfFailed pf(value); QCOMPARE(qPopulationCount(value), expected); } +// Number of test-cases per offset into each size (arbitrary): +static constexpr int casesPerOffset = 3; + void tst_QAlgorithms::countTrailing_data_impl(size_t sizeof_T_Int) { using namespace QTest; addColumn<quint64>("input"); addColumn<uint>("expected"); - int nibs = sizeof_T_Int*2; - - newRow(("0x"+QByteArray::number(0,16).rightJustified(nibs,'0')).constData()) << Q_UINT64_C(0) << uint(sizeof_T_Int*8); + addRow("0") << Q_UINT64_C(0) << uint(sizeof_T_Int*8); for (uint i = 0; i < sizeof_T_Int*8; ++i) { const quint64 input = Q_UINT64_C(1) << i; - newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << i; + addRow("bit-%u", i) << input << i; } quint64 type_mask; @@ -301,12 +317,12 @@ void tst_QAlgorithms::countTrailing_data_impl(size_t sizeof_T_Int) // and some random ones: for (uint i = 0; i < sizeof_T_Int*8; ++i) { - for (uint j = 0; j < sizeof_T_Int*3; ++j) { // 3 is arbitrary + const quint64 b = Q_UINT64_C(1) << i; + const quint64 mask = ((~(b - 1)) ^ b) & type_mask; + for (uint j = 0; j < sizeof_T_Int * casesPerOffset; ++j) { const quint64 r = QRandomGenerator::global()->generate64(); - const quint64 b = Q_UINT64_C(1) << i; - const quint64 mask = ((~(b-1)) ^ b) & type_mask; const quint64 input = (r&mask) | b; - newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << i; + addRow("%u-bits-random-%u", i, j) << input << i; } } } @@ -318,7 +334,7 @@ void tst_QAlgorithms::countTrailing_impl() QFETCH(uint, expected); const T_Int value = static_cast<T_Int>(input); - + PrintIfFailed pf(value); QCOMPARE(qCountTrailingZeroBits(value), expected); } @@ -328,22 +344,20 @@ void tst_QAlgorithms::countLeading_data_impl(size_t sizeof_T_Int) addColumn<quint64>("input"); addColumn<uint>("expected"); - int nibs = sizeof_T_Int*2; - - newRow(("0x"+QByteArray::number(0,16).rightJustified(nibs,'0')).constData()) << Q_UINT64_C(0) << uint(sizeof_T_Int*8); + addRow("0") << Q_UINT64_C(0) << uint(sizeof_T_Int*8); for (uint i = 0; i < sizeof_T_Int*8; ++i) { const quint64 input = Q_UINT64_C(1) << i; - newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << uint(sizeof_T_Int*8-i-1); + addRow("bit-%u", i) << input << uint(sizeof_T_Int*8-i-1); } // and some random ones: for (uint i = 0; i < sizeof_T_Int*8; ++i) { - for (uint j = 0; j < sizeof_T_Int*3; ++j) { // 3 is arbitrary + const quint64 b = Q_UINT64_C(1) << i; + const quint64 mask = b - 1; + for (uint j = 0; j < sizeof_T_Int * casesPerOffset; ++j) { const quint64 r = QRandomGenerator::global()->generate64(); - const quint64 b = Q_UINT64_C(1) << i; - const quint64 mask = b-1; const quint64 input = (r&mask) | b; - newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << uint(sizeof_T_Int*8-i-1); + addRow("%u-bits-random-%u", i, j) << input << uint(sizeof_T_Int*8-i-1); } } } @@ -355,7 +369,7 @@ void tst_QAlgorithms::countLeading_impl() QFETCH(uint, expected); const T_Int value = static_cast<T_Int>(input); - + PrintIfFailed pf(value); QCOMPARE(qCountLeadingZeroBits(value), expected); } diff --git a/tests/auto/corelib/tools/qarraydata/CMakeLists.txt b/tests/auto/corelib/tools/qarraydata/CMakeLists.txt index 0a0dc353ab..1d84630de2 100644 --- a/tests/auto/corelib/tools/qarraydata/CMakeLists.txt +++ b/tests/auto/corelib/tools/qarraydata/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qarraydata.pro. - ##################################################################### ## tst_qarraydata Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qarraydata LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qarraydata EXCEPTIONS SOURCES diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index f433743911..b92cd4a887 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QARRAY_TEST_SIMPLE_VECTOR_H @@ -28,7 +28,7 @@ public: } explicit SimpleVector(size_t n, bool capacityReserved = false) - : d(Data::allocate(n)) + : d(n) { if (n) d->appendInitialize(n); @@ -37,7 +37,7 @@ public: } SimpleVector(size_t n, const T &t, bool capacityReserved = false) - : d(Data::allocate(n)) + : d(n) { if (n) d->copyAppend(n, t); @@ -46,7 +46,7 @@ public: } SimpleVector(const T *begin, const T *end, bool capacityReserved = false) - : d(Data::allocate(end - begin)) + : d(end - begin) { if (end - begin) d->copyAppend(begin, end); @@ -59,11 +59,6 @@ public: { } - explicit SimpleVector(QPair<Data*, T*> ptr, size_t len = 0) - : d(ptr, len) - { - } - SimpleVector(const QArrayDataPointer<T> &other) : d(other) { @@ -135,7 +130,7 @@ public: } } - SimpleVector detached(Data::allocate(qMax(n, size()))); + SimpleVector detached(DataPointer(qMax(n, size()))); if (size()) { detached.d->copyAppend(constBegin(), constEnd()); detached.d->setFlag(QArrayData::CapacityReserved); @@ -149,7 +144,7 @@ public: return; if (d->needsDetach() || newSize > capacity()) { - SimpleVector detached(Data::allocate(d->detachCapacity(newSize))); + SimpleVector detached(DataPointer(d->detachCapacity(newSize))); if (newSize) { if (newSize < size()) { const T *const begin = constBegin(); @@ -223,7 +218,7 @@ public: const T *const end = begin + d->size; if (d->needsDetach()) { - SimpleVector detached(Data::allocate(d->detachCapacity(size() - (last - first)))); + SimpleVector detached(DataPointer(d->detachCapacity(size() - (last - first)))); if (first != begin) detached.d->copyAppend(begin, first); detached.d->copyAppend(last, end); diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 987cee0349..e7a84d57ee 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses #include <QTest> #include <QtCore/QString> @@ -106,8 +107,8 @@ void tst_QArrayData::simpleVector() SimpleVector<int> v4(nullptr, data, 0); SimpleVector<int> v5(nullptr, data, 1); SimpleVector<int> v6(nullptr, data, 7); - SimpleVector<int> v7(10, 5); - SimpleVector<int> v8(array, array + sizeof(array)/sizeof(*array)); + const SimpleVector<int> v7(10, 5); + const SimpleVector<int> v8(array, array + sizeof(array)/sizeof(*array)); v3 = v1; v1.swap(v3); @@ -235,7 +236,7 @@ void tst_QArrayData::simpleVector() { int count = 0; - Q_FOREACH (int value, v7) { + for (int value : v7) { QCOMPARE(value, 5); ++count; } @@ -245,7 +246,7 @@ void tst_QArrayData::simpleVector() { int count = 0; - Q_FOREACH (int value, v8) { + for (int value : v8) { QCOMPARE(value, count); ++count; } @@ -483,7 +484,7 @@ void tst_QArrayData::allocate() keeper.headers.append(data); if (grow) - QVERIFY(data->allocatedCapacity() > capacity); + QCOMPARE_GE(data->allocatedCapacity(), capacity); else QCOMPARE(data->allocatedCapacity(), capacity); @@ -1115,8 +1116,7 @@ void tst_QArrayData::arrayOpsExtra() const auto cloneArrayDataPointer = [] (auto &dataPointer, size_t capacity) { using ArrayPointer = std::decay_t<decltype(dataPointer)>; - using Type = std::decay_t<typename ArrayPointer::parameter_type>; - ArrayPointer copy(QTypedArrayData<Type>::allocate(qsizetype(capacity))); + ArrayPointer copy{qsizetype(capacity)}; copy->copyAppend(dataPointer.begin(), dataPointer.end()); return copy; }; @@ -2036,7 +2036,7 @@ void tst_QArrayData::dataPointerAllocate() const auto createDataPointer = [] (qsizetype capacity, auto initValue) { using Type = std::decay_t<decltype(initValue)>; Q_UNUSED(initValue); - return QArrayDataPointer<Type>(QTypedArrayData<Type>::allocate(capacity)); + return QArrayDataPointer<Type>(capacity); }; const auto testRealloc = [&] (qsizetype capacity, qsizetype newSize, auto initValue) { @@ -2452,7 +2452,7 @@ void tst_QArrayData::relocateWithExceptions() }; const auto createDataPointer = [](qsizetype capacity, qsizetype initSize) { - QArrayDataPointer<ThrowingType> qadp(QTypedArrayData<ThrowingType>::allocate(capacity)); + QArrayDataPointer<ThrowingType> qadp(capacity); qadp->appendInitialize(initSize); int i = 0; std::generate(qadp.begin(), qadp.end(), [&i]() { return ThrowingType(i++); }); diff --git a/tests/auto/corelib/tools/qatomicscopedvaluerollback/CMakeLists.txt b/tests/auto/corelib/tools/qatomicscopedvaluerollback/CMakeLists.txt index b6f29d5b7f..b20e56421f 100644 --- a/tests/auto/corelib/tools/qatomicscopedvaluerollback/CMakeLists.txt +++ b/tests/auto/corelib/tools/qatomicscopedvaluerollback/CMakeLists.txt @@ -1,9 +1,13 @@ # 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_qatomicscopedvaluerollback LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qatomicscopedvaluerollback SOURCES tst_qatomicscopedvaluerollback.cpp - LIBRARIES - Qt::CorePrivate ) diff --git a/tests/auto/corelib/tools/qatomicscopedvaluerollback/tst_qatomicscopedvaluerollback.cpp b/tests/auto/corelib/tools/qatomicscopedvaluerollback/tst_qatomicscopedvaluerollback.cpp index 81d8242f71..89bd1d7ff6 100644 --- a/tests/auto/corelib/tools/qatomicscopedvaluerollback/tst_qatomicscopedvaluerollback.cpp +++ b/tests/auto/corelib/tools/qatomicscopedvaluerollback/tst_qatomicscopedvaluerollback.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <QtCore/private/qatomicscopedvaluerollback_p.h> +#include <QtCore/qatomicscopedvaluerollback.h> #include <QTest> @@ -24,23 +24,30 @@ void tst_QAtomicScopedValueRollback::leavingScope() QAtomicInt i = 0; QBasicAtomicInteger<bool> b = false; std::atomic<bool> b2 = false; + int x = 0, y = 42; + QBasicAtomicPointer<int> p = &x; //test rollback on going out of scope { QAtomicScopedValueRollback ri(i); QAtomicScopedValueRollback rb(b); QAtomicScopedValueRollback rb2(b2, true); + QAtomicScopedValueRollback rp(p); QCOMPARE(b.loadRelaxed(), false); QCOMPARE(b2, true); QCOMPARE(i.loadRelaxed(), 0); + QCOMPARE(p.loadRelaxed(), &x); b.storeRelaxed(true); i.storeRelaxed(1); + p.storeRelaxed(&y); QCOMPARE(b.loadRelaxed(), true); QCOMPARE(i.loadRelaxed(), 1); + QCOMPARE(p.loadRelaxed(), &y); } QCOMPARE(b.loadRelaxed(), false); QCOMPARE(b2, false); QCOMPARE(i.loadRelaxed(), 0); + QCOMPARE(p.loadRelaxed(), &x); } void tst_QAtomicScopedValueRollback::leavingScopeAfterCommit() diff --git a/tests/auto/corelib/tools/qbitarray/CMakeLists.txt b/tests/auto/corelib/tools/qbitarray/CMakeLists.txt index 22401f7f3f..ac3bd24bd5 100644 --- a/tests/auto/corelib/tools/qbitarray/CMakeLists.txt +++ b/tests/auto/corelib/tools/qbitarray/CMakeLists.txt @@ -1,13 +1,19 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qbitarray.pro. - ##################################################################### ## tst_qbitarray Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbitarray LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qbitarray SOURCES tst_qbitarray.cpp + LIBRARIES + Qt::TestPrivate ) diff --git a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp index 3e755e67da..f52a368aa9 100644 --- a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp +++ b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp @@ -1,22 +1,26 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> +#include <QtTest/private/qcomparisontesthelper_p.h> #include <QtCore/QBuffer> #include <QtCore/QDataStream> #include "qbitarray.h" +#include <QtCore/qelapsedtimer.h> +#include <QtCore/qscopeguard.h> + /** * Helper function to initialize a bitarray from a string */ static QBitArray QStringToQBitArray(const QString &str) { QBitArray ba; - ba.resize(str.length()); + ba.resize(str.size()); int i; QChar tru('1'); - for (i = 0; i < str.length(); i++) + for (i = 0; i < str.size(); i++) { if (str.at(i) == tru) { @@ -26,10 +30,18 @@ static QBitArray QStringToQBitArray(const QString &str) return ba; } +static QBitArray detached(QBitArray a) +{ + a.detach(); + return a; +} + class tst_QBitArray : public QObject { Q_OBJECT private slots: + void compareCompiles(); + void canHandleIntMaxBits(); void size_data(); void size(); void countBits_data(); @@ -43,12 +55,21 @@ private slots: // operator &= void operator_andeq_data(); void operator_andeq(); + // operator & + void operator_and_data() { operator_andeq_data(); } + void operator_and(); // operator |= void operator_oreq_data(); void operator_oreq(); + // operator | + void operator_or_data() { operator_oreq_data(); } + void operator_or(); // operator ^= void operator_xoreq_data(); void operator_xoreq(); + // operator ^ + void operator_xor_data() { operator_xoreq_data(); } + void operator_xor(); // operator ~ void operator_neg_data(); void operator_neg(); @@ -66,6 +87,59 @@ private slots: void toUInt32(); }; +void tst_QBitArray::compareCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile<QBitArray>(); +} + +void tst_QBitArray::canHandleIntMaxBits() +{ + QElapsedTimer timer; + timer.start(); + const auto print = qScopeGuard([&] { + qDebug("Function took %lldms", qlonglong(timer.elapsed())); + }); + + try { + constexpr qsizetype Size1 = sizeof(void*) > sizeof(int) ? qsizetype(INT_MAX) + 2 : + INT_MAX - 2; + constexpr qsizetype Size2 = Size1 + 2; + + QBitArray ba(Size1, true); + QCOMPARE(ba.size(), Size1); + QCOMPARE(ba.at(Size1 - 1), true); + + ba.resize(Size2); + QCOMPARE(ba.size(), Size2); + QCOMPARE(ba.at(Size1 - 1), true); + QCOMPARE(ba.at(Size1), false); + QCOMPARE(ba.at(Size2 - 1), false); + + QByteArray serialized; + if constexpr (sizeof(void*) > sizeof(int)) { + QDataStream ds(&serialized, QIODevice::WriteOnly); + ds.setVersion(QDataStream::Qt_5_15); + ds << ba; + QCOMPARE(ds.status(), QDataStream::Status::SizeLimitExceeded); + serialized.clear(); + } + { + QDataStream ds(&serialized, QIODevice::WriteOnly); + ds << ba; + QCOMPARE(ds.status(), QDataStream::Status::Ok); + } + { + QDataStream ds(serialized); + QBitArray ba2; + ds >> ba2; + QCOMPARE(ds.status(), QDataStream::Status::Ok); + QT_TEST_EQUALITY_OPS(ba, ba2, true); + } + } catch (const std::bad_alloc &) { + QSKIP("Failed to allocate sufficient memory"); + } +} + void tst_QBitArray::size_data() { //create the testtable instance and define the elements @@ -125,7 +199,6 @@ void tst_QBitArray::countBits_data() QTest::newRow("11111111111111111111111111111111") << QString("11111111111111111111111111111111") << 32 << 32; QTest::newRow("11111111111111111111111111111111111111111111111111111111") << QString("11111111111111111111111111111111111111111111111111111111") << 56 << 56; - QTest::newRow("00000000000000000000000000000000000") << QString("00000000000000000000000000000000000") << 35 << 0; QTest::newRow("00000000000000000000000000000000") << QString("00000000000000000000000000000000") << 32 << 0; QTest::newRow("00000000000000000000000000000000000000000000000000000000") << QString("00000000000000000000000000000000000000000000000000000000") << 56 << 0; @@ -143,6 +216,8 @@ void tst_QBitArray::countBits() bits.setBit(i); } + QCOMPARE(bits.size(), numBits); + // NOLINTNEXTLINE(qt-port-to-std-compatible-api): We want to test count() and size() QCOMPARE(bits.count(), numBits); QCOMPARE(bits.count(true), onBits); QCOMPARE(bits.count(false), numBits - onBits); @@ -198,14 +273,20 @@ void tst_QBitArray::isEmpty() QVERIFY(!a1.isEmpty()); QVERIFY(!a1.isNull()); QVERIFY(a1.size() == 2); + + QT_TEST_EQUALITY_OPS(a1, a2, false); + QT_TEST_EQUALITY_OPS(a2, a3, false); + QT_TEST_EQUALITY_OPS(QBitArray(), QBitArray(), true); + a3 = a2; + QT_TEST_EQUALITY_OPS(a2, a3, true); } void tst_QBitArray::swap() { QBitArray b1 = QStringToQBitArray("1"), b2 = QStringToQBitArray("10"); b1.swap(b2); - QCOMPARE(b1,QStringToQBitArray("10")); - QCOMPARE(b2,QStringToQBitArray("1")); + QT_TEST_EQUALITY_OPS(b1,QStringToQBitArray("10"), true); + QT_TEST_EQUALITY_OPS(b2,QStringToQBitArray("1"), true); } void tst_QBitArray::fill() @@ -255,7 +336,7 @@ void tst_QBitArray::toggleBit() input.toggleBit(index); - QCOMPARE(input, res); + QT_TEST_EQUALITY_OPS(input, res, true); } void tst_QBitArray::operator_andeq_data() @@ -300,9 +381,64 @@ void tst_QBitArray::operator_andeq() QFETCH(QBitArray, input2); QFETCH(QBitArray, res); - input1&=input2; + QBitArray result = input1; + result &= input2; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1; + result &= std::move(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1; + result &= detached(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is commutative + result = input2; + result &= input1; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2; + result &= std::move(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2; + result &= detached(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is idempotent + result &= result; + QT_TEST_EQUALITY_OPS(result, res, true); + result &= std::move(result); + QT_TEST_EQUALITY_OPS(result, res, true); + result &= detached(result); + QT_TEST_EQUALITY_OPS(result, res, true); +} - QCOMPARE(input1, res); +void tst_QBitArray::operator_and() +{ + QFETCH(QBitArray, input1); + QFETCH(QBitArray, input2); + QFETCH(QBitArray, res); + + QBitArray result = input1 & input2; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1 & QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1 & detached(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is commutative + result = input2 & input1; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2 & QBitArray(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2 & detached(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is idempotent + result = result & result; + QT_TEST_EQUALITY_OPS(result, res, true); + result = result & QBitArray(result); + QT_TEST_EQUALITY_OPS(result, res, true); + result = result & detached(result); + QT_TEST_EQUALITY_OPS(result, res, true); } void tst_QBitArray::operator_oreq_data() @@ -351,9 +487,64 @@ void tst_QBitArray::operator_oreq() QFETCH(QBitArray, input2); QFETCH(QBitArray, res); - input1|=input2; + QBitArray result = input1; + result |= input2; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1; + result |= QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1; + result |= detached(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is commutative + result = input2; + result |= input1; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2; + result |= QBitArray(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2; + result |= detached(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is idempotent + result |= result; + QT_TEST_EQUALITY_OPS(result, res, true); + result |= QBitArray(result); + QT_TEST_EQUALITY_OPS(result, res, true); + result |= detached(result); + QT_TEST_EQUALITY_OPS(result, res, true); +} + +void tst_QBitArray::operator_or() +{ + QFETCH(QBitArray, input1); + QFETCH(QBitArray, input2); + QFETCH(QBitArray, res); - QCOMPARE(input1, res); + QBitArray result = input1 | input2; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1 | QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1 | detached(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is commutative + result = input2 | input1; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2 | QBitArray(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2 | detached(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is idempotent + result = result | result; + QT_TEST_EQUALITY_OPS(result, res, true); + result = result | QBitArray(result); + QT_TEST_EQUALITY_OPS(result, res, true); + result = result | detached(result); + QT_TEST_EQUALITY_OPS(result, res, true); } void tst_QBitArray::operator_xoreq_data() @@ -400,11 +591,102 @@ void tst_QBitArray::operator_xoreq() QFETCH(QBitArray, input2); QFETCH(QBitArray, res); - input1^=input2; - - QCOMPARE(input1, res); + QBitArray result = input1; + result ^= input2; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1; + result ^= QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1; + result ^= detached(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is commutative + result = input2; + result ^= input1; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2; + result ^= QBitArray(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2; + result ^= detached(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + + // XORing with oneself is nilpotent + result = input1; + result ^= input1; + QT_TEST_EQUALITY_OPS(result, QBitArray(input1.size()), true); + result = input1; + result ^= QBitArray(result); + QT_TEST_EQUALITY_OPS(result, QBitArray(input1.size()), true); + result = input1; + result ^= detached(result); + QT_TEST_EQUALITY_OPS(result, QBitArray(input1.size()), true); + + result = input2; + result ^= input2; + QT_TEST_EQUALITY_OPS(result, QBitArray(input2.size()), true); + result = input2; + result ^= QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, QBitArray(input2.size()), true); + result = input2; + result ^= detached(input2); + QT_TEST_EQUALITY_OPS(result, QBitArray(input2.size()), true); + + result = res; + result ^= res; + QT_TEST_EQUALITY_OPS(result, QBitArray(res.size()), true); + result = res; + result ^= QBitArray(res); + QT_TEST_EQUALITY_OPS(result, QBitArray(res.size()), true); + result = res; + result ^= detached(res); + QT_TEST_EQUALITY_OPS(result, QBitArray(res.size()), true); } +void tst_QBitArray::operator_xor() +{ + QFETCH(QBitArray, input1); + QFETCH(QBitArray, input2); + QFETCH(QBitArray, res); + + QBitArray result = input1 ^ input2; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1 ^ QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input1 ^ detached(input2); + QT_TEST_EQUALITY_OPS(result, res, true); + + // operation is commutative + result = input2 ^ input1; + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2 ^ QBitArray(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + result = input2 ^ detached(input1); + QT_TEST_EQUALITY_OPS(result, res, true); + + // XORing with oneself is nilpotent + result = input1 ^ input1; + QT_TEST_EQUALITY_OPS(result, QBitArray(input1.size()), true); + result = input1 ^ QBitArray(input1); + QT_TEST_EQUALITY_OPS(result, QBitArray(input1.size()), true); + result = input1 ^ detached(input1); + QT_TEST_EQUALITY_OPS(result, QBitArray(input1.size()), true); + + result = input2 ^ input2; + QT_TEST_EQUALITY_OPS(result, QBitArray(input2.size()), true); + result = input2 ^ QBitArray(input2); + QT_TEST_EQUALITY_OPS(result, QBitArray(input2.size()), true); + result = input2 ^ detached(input2); + QT_TEST_EQUALITY_OPS(result, QBitArray(input2.size()), true); + + result = res ^ res; + QT_TEST_EQUALITY_OPS(result, QBitArray(res.size()), true); + result = res ^ QBitArray(res); + QT_TEST_EQUALITY_OPS(result, QBitArray(res.size()), true); + result = res ^ detached(res); + QT_TEST_EQUALITY_OPS(result, QBitArray(res.size()), true); +} void tst_QBitArray::operator_neg_data() { @@ -452,7 +734,8 @@ void tst_QBitArray::operator_neg() input = ~input; - QCOMPARE(input, res); + QT_TEST_EQUALITY_OPS(input, res, true); + QT_TEST_EQUALITY_OPS(~~input, res, true); // performs two in-place negations } void tst_QBitArray::datastream_data() @@ -472,7 +755,6 @@ void tst_QBitArray::datastream_data() QTest::newRow("11111111111111111111111111111111") << QString("11111111111111111111111111111111") << 32 << 32; QTest::newRow("11111111111111111111111111111111111111111111111111111111") << QString("11111111111111111111111111111111111111111111111111111111") << 56 << 56; - QTest::newRow("00000000000000000000000000000000000") << QString("00000000000000000000000000000000000") << 35 << 0; QTest::newRow("00000000000000000000000000000000") << QString("00000000000000000000000000000000") << 32 << 0; QTest::newRow("00000000000000000000000000000000000000000000000000000000") << QString("00000000000000000000000000000000000000000000000000000000") << 56 << 0; @@ -494,7 +776,7 @@ void tst_QBitArray::datastream() bits.setBit(i); } - QCOMPARE(bits.count(), numBits); + QCOMPARE(bits.size(), numBits); QCOMPARE(bits.count(true), onBits); QCOMPARE(bits.count(false), numBits - onBits); @@ -509,19 +791,19 @@ void tst_QBitArray::datastream() QBitArray array1, array2, array3; stream2 >> array1 >> array2 >> array3; - QCOMPARE(array1.count(), numBits); + QCOMPARE(array1.size(), numBits); QCOMPARE(array1.count(true), onBits); QCOMPARE(array1.count(false), numBits - onBits); - QCOMPARE(array1, bits); - QCOMPARE(array2, bits); - QCOMPARE(array3, bits); + QT_TEST_EQUALITY_OPS(array1, bits, true); + QT_TEST_EQUALITY_OPS(array2, bits, true); + QT_TEST_EQUALITY_OPS(array3, bits, true); } void tst_QBitArray::invertOnNull() const { QBitArray a; - QCOMPARE(a = ~a, QBitArray()); + QT_TEST_EQUALITY_OPS(a = ~a, QBitArray(), true); } void tst_QBitArray::operator_noteq_data() @@ -562,7 +844,7 @@ void tst_QBitArray::operator_noteq() QFETCH(bool, res); bool b = input1 != input2; - QCOMPARE(b, res); + QT_TEST_EQUALITY_OPS(b, res, true); } void tst_QBitArray::resize() @@ -571,22 +853,22 @@ void tst_QBitArray::resize() QBitArray a = QStringToQBitArray(QString("11")); a.resize(10); QVERIFY(a.size() == 10); - QCOMPARE( a, QStringToQBitArray(QString("1100000000")) ); + QT_TEST_EQUALITY_OPS( a, QStringToQBitArray(QString("1100000000")), true); a.setBit(9); a.resize(9); // now the bit in a should have been gone: - QCOMPARE( a, QStringToQBitArray(QString("110000000")) ); + QT_TEST_EQUALITY_OPS( a, QStringToQBitArray(QString("110000000")), true); // grow the array back and check the new bit a.resize(10); - QCOMPARE( a, QStringToQBitArray(QString("1100000000")) ); + QT_TEST_EQUALITY_OPS( a, QStringToQBitArray(QString("1100000000")), true); // other test with and a.resize(9); QBitArray b = QStringToQBitArray(QString("1111111111")); b &= a; - QCOMPARE( b, QStringToQBitArray(QString("1100000000")) ); + QT_TEST_EQUALITY_OPS( b, QStringToQBitArray(QString("1100000000")), true); } @@ -640,9 +922,9 @@ void tst_QBitArray::fromBits() QFETCH(QBitArray, expected); QBitArray fromBits = QBitArray::fromBits(data, size); - QCOMPARE(fromBits, expected); + QT_TEST_EQUALITY_OPS(fromBits, expected, true); - QCOMPARE(QBitArray::fromBits(fromBits.bits(), fromBits.size()), expected); + QT_TEST_EQUALITY_OPS(QBitArray::fromBits(fromBits.bits(), fromBits.size()), expected, true); } void tst_QBitArray::toUInt32_data() diff --git a/tests/auto/corelib/tools/qcache/CMakeLists.txt b/tests/auto/corelib/tools/qcache/CMakeLists.txt index f25dd5b068..8ffe942d70 100644 --- a/tests/auto/corelib/tools/qcache/CMakeLists.txt +++ b/tests/auto/corelib/tools/qcache/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qcache.pro. - ##################################################################### ## tst_qcache Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcache LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcache SOURCES tst_qcache.cpp diff --git a/tests/auto/corelib/tools/qcache/tst_qcache.cpp b/tests/auto/corelib/tools/qcache/tst_qcache.cpp index 0e018e18b8..5fccb8f1d0 100644 --- a/tests/auto/corelib/tools/qcache/tst_qcache.cpp +++ b/tests/auto/corelib/tools/qcache/tst_qcache.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/tools/qcommandlineparser/CMakeLists.txt b/tests/auto/corelib/tools/qcommandlineparser/CMakeLists.txt index 89c1e99a33..5aa8bd2500 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/CMakeLists.txt +++ b/tests/auto/corelib/tools/qcommandlineparser/CMakeLists.txt @@ -5,6 +5,12 @@ ## tst_qcommandlineparser Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcommandlineparser LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcommandlineparser SOURCES tst_qcommandlineparser.cpp diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/CMakeLists.txt b/tests/auto/corelib/tools/qcommandlineparser/testhelper/CMakeLists.txt index 5bda61fe28..20cec30a9c 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/CMakeLists.txt +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/CMakeLists.txt @@ -1,8 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qcommandlineparser_test_helper.pro. - ##################################################################### ## qcommandlineparser_test_helper Binary: ##################################################################### diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp index 758251f05a..b5f178a3d1 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2013 David Faure <faure@kde.org> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QDebug> #include <QCoreApplication> diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index c2f6811d27..812cf2d1b3 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2021 David Faure <faure@kde.org> // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #if QT_CONFIG(process) @@ -126,6 +126,7 @@ void tst_QCommandLineParser::testBooleanOption() QVERIFY(parser.parse(args)); QCOMPARE(parser.optionNames(), expectedOptionNames); QCOMPARE(parser.isSet("b"), expectedIsSet); + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not expecting values: \"b\""); QCOMPARE(parser.values("b"), QStringList()); QCOMPARE(parser.positionalArguments(), QStringList()); // Should warn on typos @@ -163,6 +164,7 @@ void tst_QCommandLineParser::testOptionsAndPositional() QVERIFY(parser.parse(args)); QCOMPARE(parser.optionNames(), expectedOptionNames); QCOMPARE(parser.isSet("b"), expectedIsSet); + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not expecting values: \"b\""); QCOMPARE(parser.values("b"), QStringList()); QCOMPARE(parser.positionalArguments(), expectedPositionalArguments); } @@ -361,6 +363,7 @@ void tst_QCommandLineParser::testProcessNotCalled() QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before isSet"); QVERIFY(!parser.isSet("b")); QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before values"); + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not expecting values: \"b\""); QCOMPARE(parser.values("b"), QStringList()); } @@ -448,37 +451,40 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes_data() QTest::addColumn<QStringList>("commandLine"); QTest::addColumn<QStringList>("expectedOptionNames"); QTest::addColumn<QStringList>("expectedOptionValues"); + QTest::addColumn<QStringList>("invalidOptionValues"); QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc" << "val") - << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val"); + << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val") + << (QStringList() << "a" << "b"); QTest::newRow("collapsed_with_equalsign_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc=val") - << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val"); + << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val") + << (QStringList() << "a" << "b"); QTest::newRow("collapsed_explicit_longoption") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("--nn") - << QStringList("nn") << QStringList(); + << QStringList("nn") << QStringList() << QStringList(); QTest::newRow("collapsed_longoption_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "--abc" << "val") - << QStringList("abc") << QStringList("val"); + << QStringList("abc") << QStringList("val") << QStringList(); QTest::newRow("compiler") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("-cab") - << QStringList("c") << QStringList("ab"); + << QStringList("c") << QStringList("ab") << QStringList(); QTest::newRow("compiler_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") - << QStringList("c") << QStringList("val"); + << QStringList("c") << QStringList("val") << QStringList(); QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc" << "val") - << QStringList("abc") << QStringList("val"); + << QStringList("abc") << QStringList("val") << QStringList(); QTest::newRow("implicitlylong_equal") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc=val") - << QStringList("abc") << QStringList("val"); + << QStringList("abc") << QStringList("val") << QStringList(); QTest::newRow("implicitlylong_longoption") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--nn") - << QStringList("nn") << QStringList(); + << QStringList("nn") << QStringList() << QStringList(); QTest::newRow("implicitlylong_longoption_value") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--abc" << "val") - << QStringList("abc") << QStringList("val"); + << QStringList("abc") << QStringList("val") << QStringList(); QTest::newRow("implicitlylong_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") - << QStringList("c") << QStringList("val"); + << QStringList("c") << QStringList("val") << QStringList(); QTest::newRow("forceshort_detached") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-I" << "45") - << QStringList("I") << QStringList("45"); + << QStringList("I") << QStringList("45") << QStringList(); QTest::newRow("forceshort_attached") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-I46") - << QStringList("I") << QStringList("46"); + << QStringList("I") << QStringList("46") << QStringList(); QTest::newRow("forceshort_mixed") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-I45" << "-nn") - << (QStringList() << "I" << "nn") << QStringList("45"); + << (QStringList() << "I" << "nn") << QStringList("45") << QStringList(); } void tst_QCommandLineParser::testSingleDashWordOptionModes() @@ -487,6 +493,7 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes() QFETCH(QStringList, commandLine); QFETCH(QStringList, expectedOptionNames); QFETCH(QStringList, expectedOptionValues); + QFETCH(QStringList, invalidOptionValues); commandLine.prepend("tst_QCommandLineParser"); @@ -503,14 +510,19 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes() QVERIFY(parser.addOption(forceShort)); QVERIFY(parser.parse(commandLine)); QCOMPARE(parser.optionNames(), expectedOptionNames); - for (int i = 0; i < expectedOptionValues.count(); ++i) - QCOMPARE(parser.value(parser.optionNames().at(i)), expectedOptionValues.at(i)); + for (int i = 0; i < expectedOptionValues.size(); ++i) { + const QString option = parser.optionNames().at(i); + if (invalidOptionValues.contains(option)) { + QByteArray msg = QLatin1String("QCommandLineParser: option not expecting values: \"%1\"").arg(option).toLatin1(); + QTest::ignoreMessage(QtWarningMsg, msg.data()); + } + QCOMPARE(parser.value(option), expectedOptionValues.at(i)); + } QCOMPARE(parser.unknownOptionNames(), QStringList()); } void tst_QCommandLineParser::testCpp11StyleInitialization() { -#if defined(Q_COMPILER_UNIFORM_INIT) QCoreApplication app(empty_argc, empty_argv); QCommandLineParser parser; @@ -524,9 +536,6 @@ void tst_QCommandLineParser::testCpp11StyleInitialization() QVERIFY(parser.parse({"tst_QCommandLineParser", "-a", "-vvv", "--infile=in.txt"})); QCOMPARE(parser.optionNames(), (QStringList{"a", "v", "v", "v", "infile"})); QCOMPARE(parser.value("infile"), QString("in.txt")); -#else - QSKIP("This test requires C++11 uniform initialization support in the compiler."); -#endif } void tst_QCommandLineParser::testVersionOption() @@ -553,7 +562,7 @@ void tst_QCommandLineParser::testVersionOption() static const char expectedOptionsHelp[] = "Options:\n" " -h, --help Displays help on commandline options.\n" - " --help-all Displays help including Qt specific options.\n" + " --help-all Displays help, including generic Qt options.\n" " -v, --version Displays version information.\n" " --load <url> Load file from URL.\n" " -o, --output <file> Set output file.\n" @@ -762,7 +771,7 @@ void tst_QCommandLineParser::testVeryLongOptionNames() output.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); #endif const QStringList lines = output.split('\n'); - const int last = lines.count() - 1; + const int last = lines.size() - 1; // Let's not compare everything, just the final parts. QCOMPARE(lines.at(last - 7), " cdefghijklmnopqrstuvwxyz"); QCOMPARE(lines.at(last - 6), " --looooooooooooong-option, --looooong-opt-alias <l Short description"); diff --git a/tests/auto/corelib/tools/qcontiguouscache/CMakeLists.txt b/tests/auto/corelib/tools/qcontiguouscache/CMakeLists.txt index a11983f1a9..5c32c34023 100644 --- a/tests/auto/corelib/tools/qcontiguouscache/CMakeLists.txt +++ b/tests/auto/corelib/tools/qcontiguouscache/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qcontiguouscache.pro. - ##################################################################### ## tst_qcontiguouscache Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcontiguouscache LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcontiguouscache SOURCES tst_qcontiguouscache.cpp diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp index 22b44a027c..ca110b1240 100644 --- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp +++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QObject> #include <QTest> @@ -50,20 +50,24 @@ void tst_QContiguousCache::empty() { QContiguousCache<int> c(10); QCOMPARE(c.capacity(), 10); + QCOMPARE(c.size(), 0); + // NOLINTNEXTLINE(qt-port-to-std-compatible-api): Test both size() and count() QCOMPARE(c.count(), 0); QVERIFY(c.isEmpty()); c.append(1); + // NOLINTNEXTLINE(qt-port-to-std-compatible-api): Test both size() and count() QCOMPARE(c.count(), 1); + QCOMPARE(c.size(), 1); QVERIFY(!c.isEmpty()); c.clear(); QCOMPARE(c.capacity(), 10); - QCOMPARE(c.count(), 0); + QCOMPARE(c.size(), 0); QVERIFY(c.isEmpty()); c.prepend(1); - QCOMPARE(c.count(), 1); + QCOMPARE(c.size(), 1); QVERIFY(!c.isEmpty()); c.clear(); - QCOMPARE(c.count(), 0); + QCOMPARE(c.size(), 0); QVERIFY(c.isEmpty()); QCOMPARE(c.capacity(), 10); } @@ -74,9 +78,9 @@ void tst_QContiguousCache::swap() c1.append(1); c1.swap(c2); QCOMPARE(c1.capacity(), 100); - QCOMPARE(c1.count(), 0 ); + QCOMPARE(c1.size(), 0 ); QCOMPARE(c2.capacity(), 10 ); - QCOMPARE(c2.count(), 1 ); + QCOMPARE(c2.size(), 1 ); } void tst_QContiguousCache::append_data() @@ -112,7 +116,7 @@ void tst_QContiguousCache::append() QCOMPARE(c.available(), qMax(qsizetype(0), cacheSize - i)); QCOMPARE(c.first(), qMax(qsizetype(1), i-cacheSize+1)); QCOMPARE(c.last(), i); - QCOMPARE(c.count(), qMin(i, cacheSize)); + QCOMPARE(c.size(), qMin(i, cacheSize)); QCOMPARE(c.isFull(), i >= cacheSize); i++; } @@ -125,7 +129,7 @@ void tst_QContiguousCache::append() // test taking from end until empty. for (j = 0; j < cacheSize; j++, i--) { QCOMPARE(c.takeLast(), i-1); - QCOMPARE(c.count(), cacheSize-j-1); + QCOMPARE(c.size(), cacheSize-j-1); QCOMPARE(c.available(), j+1); QVERIFY(!c.isFull()); QCOMPARE(c.isEmpty(), j==cacheSize-1); @@ -163,7 +167,7 @@ void tst_QContiguousCache::prepend() QCOMPARE(c.available(), qMax(0, cacheSize - i)); QCOMPARE(c.last(), qMax(1, i-cacheSize+1)); QCOMPARE(c.first(), i); - QCOMPARE(c.count(), qMin(i, cacheSize)); + QCOMPARE(c.size(), qMin(i, cacheSize)); QCOMPARE(c.isFull(), i >= cacheSize); i++; } @@ -176,7 +180,7 @@ void tst_QContiguousCache::prepend() // test taking from start until empty. for (j = 0; j < cacheSize; j++, i--) { QCOMPARE(c.takeFirst(), i-1); - QCOMPARE(c.count(), cacheSize-j-1); + QCOMPARE(c.size(), cacheSize-j-1); QCOMPARE(c.available(), j+1); QVERIFY(!c.isFull()); QCOMPARE(c.isEmpty(), j==cacheSize-1); @@ -296,7 +300,7 @@ void tst_QContiguousCache::setCapacity() for (i = 280; i < 310; ++i) contiguousCache.insert(i, i); QCOMPARE(contiguousCache.capacity(), 100); - QCOMPARE(contiguousCache.count(), 30); + QCOMPARE(contiguousCache.size(), 30); QCOMPARE(contiguousCache.firstIndex(), 280); QCOMPARE(contiguousCache.lastIndex(), 309); @@ -308,7 +312,7 @@ void tst_QContiguousCache::setCapacity() contiguousCache.setCapacity(150); QCOMPARE(contiguousCache.capacity(), 150); - QCOMPARE(contiguousCache.count(), 30); + QCOMPARE(contiguousCache.size(), 30); QCOMPARE(contiguousCache.firstIndex(), 280); QCOMPARE(contiguousCache.lastIndex(), 309); @@ -320,7 +324,7 @@ void tst_QContiguousCache::setCapacity() contiguousCache.setCapacity(20); QCOMPARE(contiguousCache.capacity(), 20); - QCOMPARE(contiguousCache.count(), 20); + QCOMPARE(contiguousCache.size(), 20); QCOMPARE(contiguousCache.firstIndex(), 290); QCOMPARE(contiguousCache.lastIndex(), 309); diff --git a/tests/auto/corelib/tools/qcryptographichash/CMakeLists.txt b/tests/auto/corelib/tools/qcryptographichash/CMakeLists.txt index 631abeac20..8a0c08fcad 100644 --- a/tests/auto/corelib/tools/qcryptographichash/CMakeLists.txt +++ b/tests/auto/corelib/tools/qcryptographichash/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qcryptographichash.pro. - ##################################################################### ## tst_qcryptographichash Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcryptographichash LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp index 2151c69323..c08afd67c4 100644 --- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp +++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QCoreApplication> @@ -8,9 +8,7 @@ #include <QCryptographicHash> #include <QtCore/QMetaEnum> -#if QT_CONFIG(cxx11_future) -# include <thread> -#endif +#include <thread> Q_DECLARE_METATYPE(QCryptographicHash::Algorithm) @@ -25,18 +23,24 @@ private slots: void sha1(); void sha3_data(); void sha3(); + void keccak(); + void keccak_data(); void blake2_data(); void blake2(); void files_data(); void files(); void hashLength_data(); void hashLength(); + void addDataAcceptsNullByteArrayView_data() { hashLength_data(); } + void addDataAcceptsNullByteArrayView(); void move(); void swap(); // keep last void moreThan4GiBOfData_data(); void moreThan4GiBOfData(); + void keccakBufferOverflow(); private: + void ensureLargeData(); std::vector<char> large; }; @@ -148,6 +152,27 @@ void tst_QCryptographicHash::intermediary_result_data() << QByteArray("abc") << QByteArray("abc") << QByteArray::fromHex("B751850B1A57168A5693CD924B6B096E08F621827444F70D884F5D0240D2712E10E116E9192AF3C91A7EC57647E3934057340B4CF408D5A56592F8274EEC53F0") << QByteArray::fromHex("BB582DA40D15399ACF62AFCBBD6CFC9EE1DD5129B1EF9935DD3B21668F1A73D7841018BE3B13F281C3A8E9DA7EDB60F57B9F9F1C04033DF4CE3654B7B2ADB310"); + + QTest::newRow("keccak_224_abc_abc") + << int(QCryptographicHash::Keccak_224) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("c30411768506ebe1c2871b1ee2e87d38df342317300a9b97a95ec6a8") + << QByteArray::fromHex("048330e7c7c8b4a41ab713b3a6f958d77b8cf3ee969930f1584dd550"); + QTest::newRow("keccak_256_abc_abc") + << int(QCryptographicHash::Keccak_256) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") + << QByteArray::fromHex("9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21"); + QTest::newRow("keccak_384_abc_abc") + << int(QCryptographicHash::Keccak_384) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("f7df1165f033337be098e7d288ad6a2f74409d7a60b49c36642218de161b1f99f8c681e4afaf31a34db29fb763e3c28e") + << QByteArray::fromHex("d733b87d392d270889d3da23ae113f349e25574b445f319cde4cd3f877c753e9e3c65980421339b3a131457ff393939f"); + QTest::newRow("keccak_512_abc_abc") + << int(QCryptographicHash::Keccak_512) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96") + << QByteArray::fromHex("a7c392d2a42155761ca76bddde1c47d55486b007edf465397bfb9dfa74d11c8f0d7c86cd29415283f1b5e7f655cec25b869c9e9c33a8986f0b38542fb12bfb93"); } void tst_QCryptographicHash::intermediary_result() @@ -254,6 +279,68 @@ void tst_QCryptographicHash::sha3() QCOMPARE(result, expectedResult); } +void tst_QCryptographicHash::keccak_data() +{ + QTest::addColumn<QCryptographicHash::Algorithm>("algorithm"); + QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("expectedResult"); + +#define ROW(Tag, Algorithm, Input, Result) \ + QTest::newRow(Tag) << Algorithm << QByteArrayLiteral(Input) << QByteArray::fromHex(Result) + + ROW("keccak_224_pangram", + QCryptographicHash::Keccak_224, + "The quick brown fox jumps over the lazy dog", + "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe"); + + ROW("keccak_224_pangram_dot", + QCryptographicHash::Keccak_224, + "The quick brown fox jumps over the lazy dog.", + "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab"); + + ROW("keccak_256_pangram", + QCryptographicHash::Keccak_256, + "The quick brown fox jumps over the lazy dog", + "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15"); + + ROW("keccak_256_pangram_dot", + QCryptographicHash::Keccak_256, + "The quick brown fox jumps over the lazy dog.", + "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d"); + + ROW("keccak_384_pangram", + QCryptographicHash::Keccak_384, + "The quick brown fox jumps over the lazy dog", + "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3"); + + ROW("keccak_384_pangram_dot", + QCryptographicHash::Keccak_384, + "The quick brown fox jumps over the lazy dog.", + "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b"); + + ROW("skeccak_512_pangram", + QCryptographicHash::Keccak_512, + "The quick brown fox jumps over the lazy dog", + "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609"); + + ROW("keccak_512_pangram_dot", + QCryptographicHash::Keccak_512, + "The quick brown fox jumps over the lazy dog.", + "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760"); + +#undef ROW +} + +void tst_QCryptographicHash::keccak() +{ + QFETCH(QCryptographicHash::Algorithm, algorithm); + QFETCH(QByteArray, data); + QFETCH(QByteArray, expectedResult); + + const auto result = QCryptographicHash::hash(data, algorithm); + QCOMPARE(result, expectedResult); +} + void tst_QCryptographicHash::blake2_data() { QTest::addColumn<QCryptographicHash::Algorithm>("algorithm"); @@ -393,7 +480,7 @@ void tst_QCryptographicHash::hashLength_data() auto metaEnum = QMetaEnum::fromType<QCryptographicHash::Algorithm>(); for (int i = 0, value = metaEnum.value(i); value != -1; value = metaEnum.value(++i)) { auto algorithm = QCryptographicHash::Algorithm(value); - QTest::addRow("%s", metaEnum.valueToKey(value)) << algorithm; + QTest::addRow("%s", metaEnum.key(i)) << algorithm; } } @@ -401,8 +488,36 @@ void tst_QCryptographicHash::hashLength() { QFETCH(const QCryptographicHash::Algorithm, algorithm); - QByteArray output = QCryptographicHash::hash("test", algorithm); - QCOMPARE(QCryptographicHash::hashLength(algorithm), output.length()); + qsizetype expectedSize; + if (algorithm == QCryptographicHash::NumAlgorithms) { + // It's UB to call ::hash() with NumAlgorithms, but hashLength() is + // fine and returns 0 for invalid values: + expectedSize = 0; + } else { + expectedSize = QCryptographicHash::hash("test", algorithm).size(); + } + QCOMPARE(QCryptographicHash::hashLength(algorithm), expectedSize); +} + +void tst_QCryptographicHash::addDataAcceptsNullByteArrayView() +{ + QFETCH(const QCryptographicHash::Algorithm, algorithm); + + if (!QCryptographicHash::supportsAlgorithm(algorithm)) + QSKIP("QCryptographicHash doesn't support this algorithm"); + + QCryptographicHash hash1(algorithm); + hash1.addData("meep"); + hash1.addData(QByteArrayView{}); // after other data + + QCryptographicHash hash2(algorithm); + hash2.addData(QByteArrayView{}); // before any other data + hash2.addData("meep"); + + const auto expected = QCryptographicHash::hash("meep", algorithm); + + QCOMPARE(hash1.resultView(), expected); + QCOMPARE(hash2.resultView(), expected); } void tst_QCryptographicHash::move() @@ -440,12 +555,14 @@ void tst_QCryptographicHash::swap() QCOMPARE(hash1.result(), QCryptographicHash::hash("test", QCryptographicHash::Sha256)); } -void tst_QCryptographicHash::moreThan4GiBOfData_data() +void tst_QCryptographicHash::ensureLargeData() { #if QT_POINTER_SIZE > 4 QElapsedTimer timer; timer.start(); const size_t GiB = 1024 * 1024 * 1024; + if (large.size() == 4 * GiB + 1) + return; try { large.resize(4 * GiB + 1, '\0'); } catch (const std::bad_alloc &) { @@ -454,7 +571,14 @@ void tst_QCryptographicHash::moreThan4GiBOfData_data() QCOMPARE(large.size(), 4 * GiB + 1); large.back() = '\1'; qDebug("created dataset in %lld ms", timer.elapsed()); +#endif +} +void tst_QCryptographicHash::moreThan4GiBOfData_data() +{ +#if QT_POINTER_SIZE > 4 + if (ensureLargeData(); large.empty()) + return; QTest::addColumn<QCryptographicHash::Algorithm>("algorithm"); auto me = QMetaEnum::fromType<QCryptographicHash::Algorithm>(); auto row = [me] (QCryptographicHash::Algorithm algo) { @@ -479,14 +603,7 @@ void tst_QCryptographicHash::moreThan4GiBOfData() { QFETCH(const QCryptographicHash::Algorithm, algorithm); -# if QT_CONFIG(cxx11_future) using MaybeThread = std::thread; -# else - struct MaybeThread { - std::function<void()> func; - void join() { func(); } - }; -# endif QElapsedTimer timer; timer.start(); @@ -517,5 +634,33 @@ void tst_QCryptographicHash::moreThan4GiBOfData() QCOMPARE(single, chunked); } +void tst_QCryptographicHash::keccakBufferOverflow() +{ +#if QT_POINTER_SIZE == 4 + QSKIP("This is a 64-bit-only test"); +#else + + if (ensureLargeData(); large.empty()) + return; + + QElapsedTimer timer; + timer.start(); + const auto sg = qScopeGuard([&] { + qDebug() << "test finished in" << timer.restart() << "ms"; + }); + + constexpr qsizetype magic = INT_MAX/4; + QCOMPARE_GE(large.size(), size_t(magic + 1)); + + QCryptographicHash hash(QCryptographicHash::Algorithm::Keccak_224); + const auto first = QByteArrayView{large}.first(1); + const auto second = QByteArrayView{large}.sliced(1, magic); + hash.addData(first); + hash.addData(second); + (void)hash.resultView(); + QVERIFY(true); // didn't crash +#endif +} + QTEST_MAIN(tst_QCryptographicHash) #include "tst_qcryptographichash.moc" diff --git a/tests/auto/corelib/tools/qduplicatetracker/CMakeLists.txt b/tests/auto/corelib/tools/qduplicatetracker/CMakeLists.txt index ee5795615b..13645c50b8 100644 --- a/tests/auto/corelib/tools/qduplicatetracker/CMakeLists.txt +++ b/tests/auto/corelib/tools/qduplicatetracker/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qduplicatetracker.pro. - ##################################################################### ## tst_qduplicatetracker Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qduplicatetracker LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qduplicatetracker SOURCES tst_qduplicatetracker.cpp diff --git a/tests/auto/corelib/tools/qduplicatetracker/tst_qduplicatetracker.cpp b/tests/auto/corelib/tools/qduplicatetracker/tst_qduplicatetracker.cpp index 8ea4802fa4..ad0b6abbc7 100644 --- a/tests/auto/corelib/tools/qduplicatetracker/tst_qduplicatetracker.cpp +++ b/tests/auto/corelib/tools/qduplicatetracker/tst_qduplicatetracker.cpp @@ -1,11 +1,13 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QtTest> #include <QtCore/private/qduplicatetracker_p.h> #include <QObject> + +#include <string> #include <utility> class tst_QDuplicateTracker : public QObject @@ -50,6 +52,27 @@ void tst_QDuplicateTracker::hasSeen() QVERIFY(!tracker.hasSeen(string3)); QVERIFY(tracker.hasSeen(string3)); } + + { + QDuplicateTracker<std::string, 2> tracker; + std::string string1("string1"); + std::string string2("string2"); + std::string string2_2("string2"); + std::string string3("string3"); + + // Move when seen + QVERIFY(!tracker.hasSeen(string1)); + QVERIFY(tracker.hasSeen(std::move(string1))); + + // Move when unseen + QVERIFY(!tracker.hasSeen(std::move(string2))); + QVERIFY(tracker.hasSeen(string2_2)); + + // Past the prealloc amount + QVERIFY(!tracker.hasSeen(string3)); + QVERIFY(tracker.hasSeen(string3)); + } + } void tst_QDuplicateTracker::clear() diff --git a/tests/auto/corelib/tools/qeasingcurve/CMakeLists.txt b/tests/auto/corelib/tools/qeasingcurve/CMakeLists.txt index 054b37827a..3f76f8a38f 100644 --- a/tests/auto/corelib/tools/qeasingcurve/CMakeLists.txt +++ b/tests/auto/corelib/tools/qeasingcurve/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qeasingcurve.pro. - ##################################################################### ## tst_qeasingcurve Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qeasingcurve LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qeasingcurve SOURCES tst_qeasingcurve.cpp diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp index 4d1d846eb8..fc8c1a3e5c 100644 --- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp +++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -374,7 +374,7 @@ void tst_QEasingCurve::valueForProgress() // in theory the baseline should't have an error of more than 0.00005 due to how its rounded, // but due to FP imprecision, we have to adjust the error a bit more. const qreal errorBound = 0.00006; - for (int i = 0; i < at.count(); ++i) { + for (int i = 0; i < at.size(); ++i) { const qreal ex = expected.at(i); const qreal error = qAbs(ex - curve.valueForProgress(at.at(i)/qreal(100))); QVERIFY(error <= errorBound); @@ -574,18 +574,18 @@ void tst_QEasingCurve::bezierSpline_data() static inline void setupBezierSpline(QEasingCurve *easingCurve, const QString &string) { - QStringList pointStr = string.split(QLatin1Char(' ')); + const QStringList pointStr = string.split(QLatin1Char(' ')); QList<QPointF> points; - foreach (const QString &str, pointStr) { + for (const QString &str : pointStr) { QStringList coordStr = str.split(QLatin1Char(',')); QPointF point(coordStr.first().toDouble(), coordStr.last().toDouble()); points.append(point); } - QVERIFY(points.count() % 3 == 0); + QVERIFY(points.size() % 3 == 0); - for (int i = 0; i < points.count() / 3; i++) { + for (int i = 0; i < points.size() / 3; i++) { QPointF c1 = points.at(i * 3); QPointF c2 = points.at(i * 3 + 1); QPointF p1 = points.at(i * 3 + 2); @@ -603,7 +603,7 @@ void tst_QEasingCurve::bezierSpline() setupBezierSpline(&bezierEasingCurve, definition); const qreal errorBound = 0.002; - for (int i = 0; i < at.count(); ++i) { + for (int i = 0; i < at.size(); ++i) { const qreal ex = expected.at(i); const qreal value = bezierEasingCurve.valueForProgress(at.at(i)/qreal(100)); const qreal error = qAbs(ex - value); @@ -642,11 +642,11 @@ void tst_QEasingCurve::tcbSpline_data() static inline void setupTCBSpline(QEasingCurve *easingCurve, const QString &string) { - QStringList pointStr = string.split(QLatin1Char(' ')); + const QStringList pointStr = string.split(QLatin1Char(' ')); - foreach (const QString &str, pointStr) { + for (const QString &str : pointStr) { QStringList coordStr = str.split(QLatin1Char(',')); - Q_ASSERT(coordStr.count() == 5); + Q_ASSERT(coordStr.size() == 5); QPointF point(coordStr.first().toDouble(), coordStr.at(1).toDouble()); qreal t = coordStr.at(2).toDouble(); qreal c = coordStr.at(3).toDouble(); @@ -665,7 +665,7 @@ void tst_QEasingCurve::tcbSpline() setupTCBSpline(&tcbEasingCurve, definition); const qreal errorBound = 0.002; - for (int i = 0; i < at.count(); ++i) { + for (int i = 0; i < at.size(); ++i) { const qreal ex = expected.at(i); const qreal value = tcbEasingCurve.valueForProgress(at.at(i)/qreal(100)); const qreal error = qAbs(ex - value); diff --git a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/CMakeLists.txt b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/CMakeLists.txt index 1e6ff08a2f..280918e302 100644 --- a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/CMakeLists.txt +++ b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qexplicitlyshareddatapointer.pro. - ##################################################################### ## tst_qexplicitlyshareddatapointer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qexplicitlyshareddatapointer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qexplicitlyshareddatapointer SOURCES tst_qexplicitlyshareddatapointer.cpp diff --git a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp index 95c2fe612d..5e105a090a 100644 --- a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp +++ b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -223,4 +223,3 @@ void tst_QExplicitlySharedDataPointer::swap() const QTEST_MAIN(tst_QExplicitlySharedDataPointer) #include "tst_qexplicitlyshareddatapointer.moc" -// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/corelib/tools/qflatmap/CMakeLists.txt b/tests/auto/corelib/tools/qflatmap/CMakeLists.txt index d5d5151973..bc98c669fc 100644 --- a/tests/auto/corelib/tools/qflatmap/CMakeLists.txt +++ b/tests/auto/corelib/tools/qflatmap/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qflatmap.pro. - ##################################################################### ## tst_qflatmap Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qflatmap LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qflatmap SOURCES tst_qflatmap.cpp diff --git a/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp b/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp index f57abbf156..986cf2407b 100644 --- a/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp +++ b/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #define QT_USE_QSTRINGBUILDER #define QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT @@ -682,7 +682,7 @@ void tst_QFlatMap::viewIterators() }); auto it = keys.begin(); QCOMPARE(*it, "kaksi"); - QCOMPARE(it->length(), 5); + QCOMPARE(it->size(), 5); ++it; QCOMPARE(*it, "kolme"); it++; @@ -703,7 +703,7 @@ void tst_QFlatMap::viewIterators() }); auto it = values.begin(); QCOMPARE(*it, "twee"); - QCOMPARE(it->length(), 4); + QCOMPARE(it->size(), 4); ++it; QCOMPARE(*it, "dree"); it++; diff --git a/tests/auto/corelib/tools/qfreelist/CMakeLists.txt b/tests/auto/corelib/tools/qfreelist/CMakeLists.txt index 23d3f51fbf..a37d3131f5 100644 --- a/tests/auto/corelib/tools/qfreelist/CMakeLists.txt +++ b/tests/auto/corelib/tools/qfreelist/CMakeLists.txt @@ -1,23 +1,19 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qfreelist.pro. - ##################################################################### ## tst_qfreelist Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfreelist LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfreelist SOURCES tst_qfreelist.cpp LIBRARIES Qt::CorePrivate ) - -## Scopes: -##################################################################### - -qt_internal_extend_target(tst_qfreelist CONDITION NOT QT_FEATURE_private_tests - SOURCES - ../../../../../src/corelib/tools/qfreelist.cpp -) diff --git a/tests/auto/corelib/tools/qfreelist/tst_qfreelist.cpp b/tests/auto/corelib/tools/qfreelist/tst_qfreelist.cpp index 1b2cd610da..a45fa6d400 100644 --- a/tests/auto/corelib/tools/qfreelist/tst_qfreelist.cpp +++ b/tests/auto/corelib/tools/qfreelist/tst_qfreelist.cpp @@ -1,6 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QCoreApplication> #include <QtCore/QElapsedTimer> @@ -116,7 +115,7 @@ public: needToRelease << i; } while (t.elapsed() < TimeLimit); - foreach (int x, needToRelease) + for (int x : std::as_const(needToRelease)) freelist.release(x); } }; diff --git a/tests/auto/corelib/tools/qhash/CMakeLists.txt b/tests/auto/corelib/tools/qhash/CMakeLists.txt index b3ed4444da..8702b8bf23 100644 --- a/tests/auto/corelib/tools/qhash/CMakeLists.txt +++ b/tests/auto/corelib/tools/qhash/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qhash.pro. - ##################################################################### ## tst_qhash Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qhash LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qhash SOURCES tst_qhash.cpp diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index bb73a267a5..b3dbdfa40c 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -1,10 +1,12 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> +#include <qdebug.h> #include <qhash.h> #include <qmap.h> +#include <qscopeguard.h> #include <qset.h> #include <algorithm> @@ -36,12 +38,24 @@ private slots: void qhash(); void take(); // copied from tst_QMap void operator_eq(); // slightly modified from tst_QMap + void heterogeneousSearch(); + void heterogeneousSearchConstKey(); + void heterogeneousSearchByteArray(); + void heterogeneousSearchString(); + void heterogeneousSearchLatin1String(); + void rehash_isnt_quadratic(); void dont_need_default_constructor(); void qmultihash_specific(); void qmultihash_qhash_rvalue_ref_ctor(); void qmultihash_qhash_rvalue_ref_unite(); void qmultihashUnite(); + void qmultihashSize(); + void qmultihashHeterogeneousSearch(); + void qmultihashHeterogeneousSearchConstKey(); + void qmultihashHeterogeneousSearchByteArray(); + void qmultihashHeterogeneousSearchString(); + void qmultihashHeterogeneousSearchLatin1String(); void compare(); void compare2(); @@ -61,6 +75,7 @@ private slots: void eraseValidIteratorOnSharedHash(); void equal_range(); void insert_hash(); + void multiHashStoresInReverseInsertionOrder(); void emplace(); @@ -76,6 +91,8 @@ private slots: void reserveShared(); void reserveLessThanCurrentAmount(); + void reserveKeepCapacity_data(); + void reserveKeepCapacity(); void QTBUG98265(); @@ -168,13 +185,13 @@ void tst_QHash::count() { MyMap map; MyMap map2( map ); - QCOMPARE( map.count(), 0 ); - QCOMPARE( map2.count(), 0 ); + QCOMPARE( map.size(), 0 ); + QCOMPARE( map2.size(), 0 ); QCOMPARE( MyClass::count, 0 ); // detach map2["Hallo"] = MyClass( "Fritz" ); - QCOMPARE( map.count(), 0 ); - QCOMPARE( map2.count(), 1 ); + QCOMPARE( map.size(), 0 ); + QCOMPARE( map2.size(), 1 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 1 ); #endif @@ -184,11 +201,11 @@ void tst_QHash::count() { typedef QHash<QString, MyClass> Map; Map map; - QCOMPARE( map.count(), 0); + QCOMPARE( map.size(), 0); map.insert( "Torben", MyClass("Weis") ); - QCOMPARE( map.count(), 1 ); + QCOMPARE( map.size(), 1 ); map.insert( "Claudia", MyClass("Sorg") ); - QCOMPARE( map.count(), 2 ); + QCOMPARE( map.size(), 2 ); map.insert( "Lars", MyClass("Linzbach") ); map.insert( "Matthias", MyClass("Ettrich") ); map.insert( "Sue", MyClass("Paludo") ); @@ -196,7 +213,7 @@ void tst_QHash::count() map.insert( "Haavard", MyClass("Nord") ); map.insert( "Arnt", MyClass("Gulbrandsen") ); map.insert( "Paul", MyClass("Tvete") ); - QCOMPARE( map.count(), 9 ); + QCOMPARE( map.size(), 9 ); map.insert( "Paul", MyClass("Tvete 1") ); map.insert( "Paul", MyClass("Tvete 2") ); map.insert( "Paul", MyClass("Tvete 3") ); @@ -204,68 +221,68 @@ void tst_QHash::count() map.insert( "Paul", MyClass("Tvete 5") ); map.insert( "Paul", MyClass("Tvete 6") ); - QCOMPARE( map.count(), 9 ); + QCOMPARE( map.size(), 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif Map map2( map ); - QVERIFY( map2.count() == 9 ); + QVERIFY( map2.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2.insert( "Kay", MyClass("Roemer") ); - QVERIFY( map2.count() == 10 ); - QVERIFY( map.count() == 9 ); + QVERIFY( map2.size() == 10 ); + QVERIFY( map.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 19 ); #endif map2 = map; - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 9 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2.insert( "Kay", MyClass("Roemer") ); - QVERIFY( map2.count() == 10 ); + QVERIFY( map2.size() == 10 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 19 ); #endif map2.clear(); - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2 = map; - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 9 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2.clear(); - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map.remove( "Lars" ); - QVERIFY( map.count() == 8 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 8 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 8 ); #endif map.remove( "Mist" ); - QVERIFY( map.count() == 8 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 8 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 8 ); #endif @@ -279,22 +296,22 @@ void tst_QHash::count() #ifndef Q_CC_SUN QVERIFY( MyClass::count == 1 ); #endif - QVERIFY( map.count() == 1 ); + QVERIFY( map.size() == 1 ); (void)map["Torben"].str; (void)map["Lars"].str; #ifndef Q_CC_SUN QVERIFY( MyClass::count == 2 ); #endif - QVERIFY( map.count() == 2 ); + QVERIFY( map.size() == 2 ); const Map& cmap = map; (void)cmap["Depp"].str; #ifndef Q_CC_SUN QVERIFY( MyClass::count == 2 ); #endif - QVERIFY( map.count() == 2 ); - QVERIFY( cmap.count() == 2 ); + QVERIFY( map.size() == 2 ); + QVERIFY( cmap.size() == 2 ); } QCOMPARE( MyClass::count, 0 ); { @@ -1152,6 +1169,222 @@ void tst_QHash::operator_eq() } } +#ifdef __cpp_concepts +struct HeterogeneousHashingType +{ + inline static int conversionCount = 0; + QString s; + + Q_IMPLICIT operator QString() const + { + ++conversionCount; + return s; + } + + // std::equality_comparable_with requires we be self-comparable too + friend bool operator==(const HeterogeneousHashingType &t1, const HeterogeneousHashingType &t2) = default; + + friend bool operator==(const QString &string, const HeterogeneousHashingType &tester) + { return tester.s == string; } + friend bool operator!=(const QString &string, const HeterogeneousHashingType &tester) + { return !(tester.s == string); } + + friend size_t qHash(const HeterogeneousHashingType &tester, size_t seed) + { return qHash(tester.s, seed); } +}; +QT_BEGIN_NAMESPACE +template <> struct QHashHeterogeneousSearch<QString, HeterogeneousHashingType> : std::true_type {}; +template <> struct QHashHeterogeneousSearch<HeterogeneousHashingType, QString> : std::true_type {}; +QT_END_NAMESPACE +static_assert(std::is_same_v<QString, std::common_type_t<QString, HeterogeneousHashingType>>); +static_assert(std::equality_comparable_with<QString, HeterogeneousHashingType>); +static_assert(QHashPrivate::HeterogeneouslySearchableWith<QString, HeterogeneousHashingType>); +static_assert(QHashPrivate::HeterogeneouslySearchableWith<HeterogeneousHashingType, QString>); + +template <typename T> struct HeterogeneousSearchTestHelper +{ + static void resetCounter() {} + static void checkCounter() {} +}; +template <> struct HeterogeneousSearchTestHelper<HeterogeneousHashingType> +{ + static void resetCounter() + { + HeterogeneousHashingType::conversionCount = 0; + } + static void checkCounter() + { + QTest::setThrowOnFail(true); + auto scopeExit = qScopeGuard([] { QTest::setThrowOnFail(false); }); + QCOMPARE(HeterogeneousHashingType::conversionCount, 0); + } +}; +#else +using HeterogeneousHashingType = QString; +#endif + +template <template <typename, typename> class Hash, typename String, typename View, typename Converter> +static void heterogeneousSearchTest(const QList<std::remove_const_t<String>> &keys, Converter conv) +{ +#ifdef __cpp_concepts + using Helper = HeterogeneousSearchTestHelper<View>; + String key = keys.last(); + String otherKey = keys.first(); + auto keyHolder = conv(key); + auto otherKeyHolder = conv(otherKey); + View keyView(keyHolder); + View otherKeyView(otherKeyHolder); + + Hash<String, qsizetype> hash; + static constexpr bool IsMultiHash = !std::is_same_v<decltype(hash.remove(String())), bool>; + hash[key] = keys.size(); + + Helper::resetCounter(); + QVERIFY(hash.contains(keyView)); + QCOMPARE_EQ(hash.count(keyView), 1); + QCOMPARE_EQ(hash.value(keyView), keys.size()); + QCOMPARE_EQ(hash.value(keyView, -1), keys.size()); + QCOMPARE_EQ(std::as_const(hash)[keyView], keys.size()); + QCOMPARE_EQ(hash.find(keyView), hash.begin()); + QCOMPARE_EQ(std::as_const(hash).find(keyView), hash.constBegin()); + QCOMPARE_EQ(hash.constFind(keyView), hash.constBegin()); + QCOMPARE_EQ(hash.equal_range(keyView), std::make_pair(hash.begin(), hash.end())); + QCOMPARE_EQ(std::as_const(hash).equal_range(keyView), + std::make_pair(hash.constBegin(), hash.constEnd())); + Helper::checkCounter(); + + QVERIFY(!hash.contains(otherKeyView)); + QCOMPARE_EQ(hash.count(otherKeyView), 0); + QCOMPARE_EQ(hash.value(otherKeyView), 0); + QCOMPARE_EQ(hash.value(otherKeyView, -1), -1); + QCOMPARE_EQ(std::as_const(hash)[otherKeyView], 0); + QCOMPARE_EQ(hash.find(otherKeyView), hash.end()); + QCOMPARE_EQ(std::as_const(hash).find(otherKeyView), hash.constEnd()); + QCOMPARE_EQ(hash.constFind(otherKeyView), hash.constEnd()); + QCOMPARE_EQ(hash.equal_range(otherKeyView), std::make_pair(hash.end(), hash.end())); + QCOMPARE_EQ(std::as_const(hash).equal_range(otherKeyView), + std::make_pair(hash.constEnd(), hash.constEnd())); + Helper::checkCounter(); + + // non-const versions + QCOMPARE_EQ(hash[keyView], keys.size()); // already there + Helper::checkCounter(); + + QCOMPARE_EQ(hash[otherKeyView], 0); // inserts + Helper::resetCounter(); + hash[otherKeyView] = INT_MAX; + Helper::checkCounter(); + + if constexpr (IsMultiHash) { + hash.insert(key, keys.size()); + QCOMPARE_EQ(hash.count(keyView), 2); + + // not depending on which of the two the current implementation finds + QCOMPARE_NE(hash.value(keyView), 0); + QCOMPARE_NE(hash.value(keyView, -1000), -1000); + QCOMPARE_NE(std::as_const(hash)[keyView], 0); + QCOMPARE_NE(hash.find(keyView), hash.end()); + QCOMPARE_NE(std::as_const(hash).find(keyView), hash.constEnd()); + QCOMPARE_NE(hash.constFind(keyView), hash.constEnd()); + QCOMPARE_NE(hash.equal_range(keyView), std::make_pair(hash.end(), hash.end())); + QCOMPARE_NE(std::as_const(hash).equal_range(keyView), + std::make_pair(hash.constEnd(), hash.constEnd())); + + // QMultiHash-specific functions + QVERIFY(hash.contains(keyView, keys.size())); + QCOMPARE_EQ(hash.count(keyView, 0), 0); + QCOMPARE_EQ(hash.count(keyView, keys.size()), 2); + QCOMPARE_EQ(hash.values(keyView), QList<qsizetype>({ keys.size(), keys.size() })); + + hash.insert(key, -keys.size()); + QCOMPARE_EQ(hash.count(keyView), 3); + QCOMPARE_EQ(hash.find(keyView, 0), hash.end()); + QCOMPARE_NE(hash.find(keyView, keys.size()), hash.end()); + QCOMPARE_NE(hash.find(keyView, -keys.size()), hash.end()); + QCOMPARE_EQ(std::as_const(hash).find(keyView, 0), hash.constEnd()); + QCOMPARE_NE(std::as_const(hash).find(keyView, keys.size()), hash.constEnd()); + QCOMPARE_NE(std::as_const(hash).find(keyView, -keys.size()), hash.constEnd()); + QCOMPARE_EQ(hash.constFind(keyView, 0), hash.constEnd()); + QCOMPARE_NE(hash.constFind(keyView, keys.size()), hash.constEnd()); + QCOMPARE_NE(hash.constFind(keyView, -keys.size()), hash.constEnd()); + + // removals + QCOMPARE_EQ(hash.remove(keyView, -keys.size()), 1); + QCOMPARE_EQ(hash.remove(keyView), 2); + } else { + // removals + QCOMPARE_EQ(hash.remove(keyView), true); + } + + QCOMPARE_EQ(hash.take(otherKeyView), INT_MAX); + QVERIFY(hash.isEmpty()); + Helper::checkCounter(); + + // repeat with more keys + for (qsizetype i = 0; i < keys.size() - 1; ++i) { + hash.insert(keys[i], -(i + 1)); + hash.insert(keys[i], i + 1); + } + + QVERIFY(!hash.contains(keyView)); + QCOMPARE_EQ(hash.count(keyView), 0); + QCOMPARE_EQ(hash.value(keyView), 0); + QCOMPARE_EQ(hash.value(keyView, -1), -1); + QCOMPARE_EQ(std::as_const(hash)[keyView], 0); + QCOMPARE_EQ(hash.find(keyView), hash.end()); + QCOMPARE_EQ(hash.constFind(keyView), hash.constEnd()); + Helper::checkCounter(); +#else + Q_UNUSED(keys); + Q_UNUSED(conv); + QSKIP("This feature requires C++20 (concepts)"); +#endif +} + +template <template <typename, typename> class Hash, typename String, typename View> +static void heterogeneousSearchTest(const QList<std::remove_const_t<String>> &keys) +{ + heterogeneousSearchTest<Hash, String, View>(keys, [](const String &s) { return View(s); }); +} + +template <template <typename, typename> class Hash, typename T> +static void heterogeneousSearchLatin1String(T) +{ + if constexpr (!T::value) { + QSKIP("QLatin1StringView and QString do not have the same hash on this platform"); + } else { + // similar to the above + auto toLatin1 = [](const QString &s) { return s.toLatin1(); }; + heterogeneousSearchTest<Hash, QString, QLatin1StringView>({ "Hello", {}, "World" }, toLatin1); + } +} + +void tst_QHash::heterogeneousSearch() +{ + heterogeneousSearchTest<QHash, QString, HeterogeneousHashingType>({ "Hello", {}, "World" }); +} + +void tst_QHash::heterogeneousSearchConstKey() +{ + // QHash<const QString, X> seen in the wild (e.g. Qt Creator) + heterogeneousSearchTest<QHash, const QString, HeterogeneousHashingType>({ "Hello", {}, "World" }); +} + +void tst_QHash::heterogeneousSearchByteArray() +{ + heterogeneousSearchTest<QHash, QByteArray, QByteArrayView>({ "Hello", {}, "World" }); +} + +void tst_QHash::heterogeneousSearchString() +{ + heterogeneousSearchTest<QHash, QString, QStringView>({ "Hello", {}, "World" }); +} + +void tst_QHash::heterogeneousSearchLatin1String() +{ + ::heterogeneousSearchLatin1String<QHash>(QHashHeterogeneousSearch<QString, QLatin1StringView>{}); +} + void tst_QHash::compare() { QHash<int, QString> hash1,hash2; @@ -1703,26 +1936,26 @@ void tst_QHash::qmultihash_specific() } QVERIFY(hash1.contains(9, 99)); - QCOMPARE(hash1.count(), 45); + QCOMPARE(hash1.size(), 45); hash1.remove(9, 99); QVERIFY(!hash1.contains(9, 99)); - QCOMPARE(hash1.count(), 44); + QCOMPARE(hash1.size(), 44); hash1.remove(9, 99); QVERIFY(!hash1.contains(9, 99)); - QCOMPARE(hash1.count(), 44); + QCOMPARE(hash1.size(), 44); hash1.remove(1, 99); - QCOMPARE(hash1.count(), 44); + QCOMPARE(hash1.size(), 44); hash1.insert(1, 99); hash1.insert(1, 99); - QCOMPARE(hash1.count(), 46); + QCOMPARE(hash1.size(), 46); hash1.remove(1, 99); - QCOMPARE(hash1.count(), 44); + QCOMPARE(hash1.size(), 44); hash1.remove(1, 99); - QCOMPARE(hash1.count(), 44); + QCOMPARE(hash1.size(), 44); { QMultiHash<int, int>::const_iterator i = hash1.constFind(1, 11); @@ -1768,10 +2001,10 @@ void tst_QHash::qmultihash_specific() } QCOMPARE(hash1.count(9), 8); - QCOMPARE(hash1.count(), 44); + QCOMPARE(hash1.size(), 44); hash1.remove(9); QCOMPARE(hash1.count(9), 0); - QCOMPARE(hash1.count(), 36); + QCOMPARE(hash1.size(), 36); { QMultiHash<int, int> map1; @@ -1787,7 +2020,7 @@ void tst_QHash::qmultihash_specific() map2.insert(42, 1); map2.insert(10, 2); map2.insert(48, 3); - QCOMPARE(map1.count(), map2.count()); + QCOMPARE(map1.size(), map2.size()); QVERIFY(map1.remove(42,5)); QVERIFY(map1 != map2); QVERIFY(map2.remove(42,5)); @@ -1796,7 +2029,7 @@ void tst_QHash::qmultihash_specific() QHash<int, int> hash; hash.insert(-1, -1); map2.unite(hash); - QCOMPARE(map2.count(), 6); + QCOMPARE(map2.size(), 6); QCOMPARE(map2[-1], -1); } } @@ -2049,6 +2282,103 @@ void tst_QHash::qmultihashUnite() } } +void tst_QHash::qmultihashSize() +{ + // QMultiHash has an extra m_size member that counts the number of values, + // while d->size (shared with QHash) counts the number of distinct keys. + { + QMultiHash<int, int> hash; + QCOMPARE(hash.size(), 0); + QVERIFY(hash.isEmpty()); + + hash.insert(0, 42); + QCOMPARE(hash.size(), 1); + QVERIFY(!hash.isEmpty()); + + hash.insert(0, 42); + QCOMPARE(hash.size(), 2); + QVERIFY(!hash.isEmpty()); + + hash.emplace(0, 42); + QCOMPARE(hash.size(), 3); + QVERIFY(!hash.isEmpty()); + + QCOMPARE(hash.take(0), 42); + QCOMPARE(hash.size(), 2); + QVERIFY(!hash.isEmpty()); + + QCOMPARE(hash.remove(0), 2); + QCOMPARE(hash.size(), 0); + QVERIFY(hash.isEmpty()); + } + + { + QMultiHash<int, int> hash; + hash.emplace(0, 0); + hash.emplace(0, 0); + QCOMPARE(hash.size(), 2); + QVERIFY(!hash.isEmpty()); + + hash.emplace(0, 1); + QCOMPARE(hash.size(), 3); + QVERIFY(!hash.isEmpty()); + + QCOMPARE(hash.remove(0, 0), 2); + QCOMPARE(hash.size(), 1); + QVERIFY(!hash.isEmpty()); + + hash.remove(0); + QCOMPARE(hash.size(), 0); + QVERIFY(hash.isEmpty()); + } + + { + QMultiHash<int, int> hash; + + hash[0] = 0; + QCOMPARE(hash.size(), 1); + QVERIFY(!hash.isEmpty()); + + hash.replace(0, 1); + QCOMPARE(hash.size(), 1); + QVERIFY(!hash.isEmpty()); + + hash.insert(0, 1); + hash.erase(hash.cbegin()); + QCOMPARE(hash.size(), 1); + QVERIFY(!hash.isEmpty()); + + hash.erase(hash.cbegin()); + QCOMPARE(hash.size(), 0); + QVERIFY(hash.isEmpty()); + } +} + +void tst_QHash::qmultihashHeterogeneousSearch() +{ + heterogeneousSearchTest<QMultiHash, QString, HeterogeneousHashingType>({ "Hello", {}, "World" }); +} + +void tst_QHash::qmultihashHeterogeneousSearchConstKey() +{ + heterogeneousSearchTest<QMultiHash, const QString, HeterogeneousHashingType>({ "Hello", {}, "World" }); +} + +void tst_QHash::qmultihashHeterogeneousSearchByteArray() +{ + heterogeneousSearchTest<QMultiHash, QByteArray, QByteArrayView>({ "Hello", {}, "World" }); +} + +void tst_QHash::qmultihashHeterogeneousSearchString() +{ + heterogeneousSearchTest<QMultiHash, QString, QStringView>({ "Hello", {}, "World" }); +} + +void tst_QHash::qmultihashHeterogeneousSearchLatin1String() +{ + ::heterogeneousSearchLatin1String<QMultiHash>(QHashHeterogeneousSearch<QString, QLatin1StringView>{}); +} + void tst_QHash::keys_values_uniqueKeys() { QMultiHash<QString, int> hash; @@ -2183,7 +2513,7 @@ void tst_QHash::twoArguments_qHash() void tst_QHash::initializerList() { QHash<int, QString> hash = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}}; - QCOMPARE(hash.count(), 2); + QCOMPARE(hash.size(), 2); QCOMPARE(hash[1], QString("hello")); QCOMPARE(hash[2], QString("initializer_list")); @@ -2193,9 +2523,9 @@ void tst_QHash::initializerList() // QCOMPARE(stdh[1], QString("bar")); QMultiHash<QString, int> multiHash{{"il", 1}, {"il", 2}, {"il", 3}}; - QCOMPARE(multiHash.count(), 3); + QCOMPARE(multiHash.size(), 3); QList<int> values = multiHash.values("il"); - QCOMPARE(values.count(), 3); + QCOMPARE(values.size(), 3); QHash<int, int> emptyHash{}; QVERIFY(emptyHash.isEmpty()); @@ -2367,7 +2697,7 @@ void tst_QHash::insert_hash() hash.insert(hash2); - QCOMPARE(hash.count(), 5); + QCOMPARE(hash.size(), 5); for (int i = 0; i < 5; ++i) QCOMPARE(hash[i], i); } @@ -2379,7 +2709,7 @@ void tst_QHash::insert_hash() hash.insert(hash2); - QCOMPARE(hash.count(), 1); + QCOMPARE(hash.size(), 1); QCOMPARE(hash[0], 5); } { @@ -2389,7 +2719,7 @@ void tst_QHash::insert_hash() hash.insert(hash2); - QCOMPARE(hash.count(), 1); + QCOMPARE(hash.size(), 1); QCOMPARE(hash[0], 5); QCOMPARE(hash, hash2); } @@ -2402,13 +2732,31 @@ void tst_QHash::insert_hash() // insert into ourself, nothing should happen hash.insert(hash); - QCOMPARE(hash.count(), 3); + QCOMPARE(hash.size(), 3); QCOMPARE(hash[0], 7); QCOMPARE(hash[2], 5); QCOMPARE(hash[7], 55); } } +void tst_QHash::multiHashStoresInReverseInsertionOrder() +{ + const QString strings[] = { + u"zero"_s, + u"null"_s, + u"nada"_s, + }; + { + QMultiHash<int, QString> hash; + for (const QString &string : strings) + hash.insert(0, string); + auto printOnFailure = qScopeGuard([&] { qDebug() << hash; }); + QVERIFY(std::equal(hash.begin(), hash.end(), + std::rbegin(strings), std::rend(strings))); + printOnFailure.dismiss(); + } +} + void tst_QHash::emplace() { { @@ -2576,13 +2924,13 @@ void tst_QHash::countInEmptyHash() { { QHash<int, int> hash; - QCOMPARE(hash.count(), 0); + QCOMPARE(hash.size(), 0); QCOMPARE(hash.count(42), 0); } { QMultiHash<int, int> hash; - QCOMPARE(hash.count(), 0); + QCOMPARE(hash.size(), 0); QCOMPARE(hash.count(42), 0); QCOMPARE(hash.count(42, 1), 0); } @@ -2693,6 +3041,40 @@ void tst_QHash::reserveLessThanCurrentAmount() } } +void tst_QHash::reserveKeepCapacity_data() +{ + QTest::addColumn<qsizetype>("requested"); + auto addRow = [](qsizetype requested) { + QTest::addRow("%td", ptrdiff_t(requested)) << requested; + }; + + QHash<int, int> testHash = {{1, 1}}; + qsizetype minCapacity = testHash.capacity(); + addRow(minCapacity - 1); + addRow(minCapacity + 0); + addRow(minCapacity + 1); + addRow(2 * minCapacity - 1); + addRow(2 * minCapacity + 0); + addRow(2 * minCapacity + 1); +} + +void tst_QHash::reserveKeepCapacity() +{ + QFETCH(qsizetype, requested); + + QHash<qsizetype, qsizetype> hash; + hash.reserve(requested); + qsizetype initialCapacity = hash.capacity(); + QCOMPARE_GE(initialCapacity, requested); + + // insert this many elements into the hash + for (qsizetype i = 0; i < requested; ++i) + hash.insert(i, i); + + // it mustn't have increased capacity after inserting the elements + QCOMPARE(hash.capacity(), initialCapacity); +} + void tst_QHash::QTBUG98265() { QMultiHash<QUuid, QByteArray> a; @@ -2711,9 +3093,6 @@ void tst_QHash::QTBUG98265() */ void tst_QHash::detachAndReferences() { -#if !QT_CONFIG(cxx11_future) - QSKIP("This test requires cxx11_future") -#else // Repeat a few times because it's not a guarantee for (int i = 0; i < 50; ++i) { QHash<char, char> hash; @@ -2751,7 +3130,6 @@ void tst_QHash::detachAndReferences() QVERIFY(hash.contains(kCopy)); QCOMPARE(hash.value(kCopy), vCopy); } -#endif } void tst_QHash::lookupUsingKeyIterator() diff --git a/tests/auto/corelib/tools/qhashfunctions/CMakeLists.txt b/tests/auto/corelib/tools/qhashfunctions/CMakeLists.txt index 6e31e68f80..6cbba503dc 100644 --- a/tests/auto/corelib/tools/qhashfunctions/CMakeLists.txt +++ b/tests/auto/corelib/tools/qhashfunctions/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qhashfunctions.pro. - ##################################################################### ## tst_qhashfunctions Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qhashfunctions LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qhashfunctions SOURCES tst_qhashfunctions.cpp diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp index 2d04579253..00ee5763ed 100644 --- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp +++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp @@ -1,10 +1,12 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// Copyright (C) 2024 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QVarLengthArray> #include <qhash.h> +#include <qfloat16.h> #include <iterator> #include <sstream> @@ -16,11 +18,11 @@ class tst_QHashFunctions : public QObject { Q_OBJECT public: - enum { - // random value - RandomSeed = 1045982819 - }; - uint seed; + // random values + static constexpr quint64 ZeroSeed = 0; + static constexpr quint64 RandomSeed32 = 1045982819; + static constexpr quint64 RandomSeed64 = QtPrivate::QHashCombine{}(RandomSeed32, RandomSeed32); + size_t seed; template <typename T1, typename T2> void stdPair_template(const T1 &t1, const T2 &t2); @@ -29,7 +31,15 @@ public slots: void init(); private Q_SLOTS: - void consistent(); + void unsignedIntegerConsistency_data(); + void unsignedIntegerConsistency(); + void signedIntegerConsistency_data(); + void signedIntegerConsistency(); + void extendedIntegerConsistency(); + void floatingPointConsistency_data(); + void floatingPointConsistency(); + void stringConsistency_data(); + void stringConsistency(); void qhash(); void qhash_of_empty_and_null_qstring(); void qhash_of_empty_and_null_qbytearray(); @@ -53,31 +63,277 @@ private Q_SLOTS: void stdPair_string_pairIntInt() { stdPair_template(QString("Hello"), std::make_pair(42, -47)); } // QTBUG-92910 void stdPair_int_pairIntPairIntInt() { stdPair_template(1, std::make_pair(2, std::make_pair(3, 4))); } + void enum_int_consistent_hash_qtbug108032(); + #if QT_DEPRECATED_SINCE(6, 6) void setGlobalQHashSeed(); #endif }; -void tst_QHashFunctions::consistent() +void tst_QHashFunctions::initTestCase() { - // QString-like - const QString s = QStringLiteral("abcdefghijklmnopqrstuvxyz").repeated(16); - QCOMPARE(qHash(s), qHash(QStringView(s))); + QTest::addColumn<quint64>("seedValue"); + + QTest::newRow("zero-seed") << ZeroSeed; + QTest::newRow("zero-seed-negated") << ~ZeroSeed; + QTest::newRow("non-zero-seed-32bit") << RandomSeed32; + QTest::newRow("non-zero-seed-32bit-negated") + << quint64{~quint32(RandomSeed32)}; // ensure this->seed gets same value on 32/64-bit + if constexpr (sizeof(size_t) == sizeof(quint64)) { + QTest::newRow("non-zero-seed-64bit") << RandomSeed64; + QTest::newRow("non-zero-seed-64bit-negated") << ~RandomSeed64; + } } -void tst_QHashFunctions::initTestCase() +void tst_QHashFunctions::init() { - static_assert(int(RandomSeed) > 0); + QFETCH_GLOBAL(quint64, seedValue); + seed = size_t(seedValue); +} - QTest::addColumn<uint>("seedValue"); - QTest::newRow("zero-seed") << 0U; - QTest::newRow("non-zero-seed") << uint(RandomSeed); +template <typename T> static void addPositiveCommonRows() +{ + QTest::addRow("zero") << T(0); + QTest::addRow("positive_7bit") << T(42); + QTest::addRow("positive_15bit") << T(0x1f3f); + QTest::addRow("positive_31bit") << T(0x4b3d'93c4); + QTest::addRow("positive_63bit") << T(Q_INT64_C(0x39df'7338'4b14'fcb0)); + + QTest::addRow("SCHAR_MAX") << T(SCHAR_MAX); + QTest::addRow("SHRT_MAX") << T(SHRT_MAX); + QTest::addRow("INT_MAX") << T(INT_MAX); + QTest::addRow("LLONG_MAX") << T(LLONG_MAX); } -void tst_QHashFunctions::init() +void tst_QHashFunctions::signedIntegerConsistency_data() +{ + QTest::addColumn<qint64>("value"); + addPositiveCommonRows<qint64>(); + QTest::addRow("negative_7bit") << Q_INT64_C(-28); + QTest::addRow("negative_15bit") << Q_INT64_C(-0x387c); + QTest::addRow("negative_31bit") << qint64(-0x7713'30f9); + + QTest::addRow("SCHAR_MIN") << qint64(SCHAR_MIN); + QTest::addRow("SHRT_MIN") << qint64(SHRT_MIN); + QTest::addRow("INT_MIN") << qint64(INT_MIN); + QTest::addRow("LLONG_MIN") << LLONG_MIN; +} + +void tst_QHashFunctions::unsignedIntegerConsistency_data() +{ + QTest::addColumn<quint64>("value"); + addPositiveCommonRows<quint64>(); + + QTest::addRow("positive_8bit") << Q_UINT64_C(0xE4); + QTest::addRow("positive_16bit") << Q_UINT64_C(0xcafe); + QTest::addRow("positive_32bit") << quint64(0xcafe'babe); + + QTest::addRow("UCHAR_MAX") << quint64(UCHAR_MAX); + QTest::addRow("UHRT_MAX") << quint64(USHRT_MAX); + QTest::addRow("UINT_MAX") << quint64(UINT_MAX); + QTest::addRow("ULLONG_MAX") << ULLONG_MAX; +} + +static void unsignedIntegerConsistency(quint64 value, size_t seed) +{ + quint8 v8 = quint8(value); + quint16 v16 = quint16(value); + quint32 v32 = quint32(value); + + const auto hu8 = qHash(v8, seed); + const auto hu16 = qHash(v16, seed); + const auto hu32 = qHash(v32, seed); + const auto hu64 = qHash(value, seed); + + if (v8 == value) + QCOMPARE(hu8, hu32); + if (v16 == value) + QCOMPARE(hu16, hu32); + if (v32 == value) + QCOMPARE(hu64, hu32); + +#if QT_SUPPORTS_INT128 + const auto hu128 = qHash(quint128(value), seed); + QCOMPARE(hu128, hu64); +#endif + + // there are a few more unsigned types: +#ifdef __cpp_char8_t + const auto hc8 = qHash(char8_t(value), seed); +#endif + const auto hc16 = qHash(char16_t(value), seed); + const auto hc32 = qHash(char32_t(value), seed); +#ifdef __cpp_char8_t + QCOMPARE(hc8, hu8); +#endif + QCOMPARE(hc16, hu16); + QCOMPARE(hc32, hu32); +} + +void tst_QHashFunctions::unsignedIntegerConsistency() +{ + QFETCH(quint64, value); + ::unsignedIntegerConsistency(value, seed); +} + +void tst_QHashFunctions::signedIntegerConsistency() +{ + QFETCH(qint64, value); + qint8 v8 = qint8(value); + qint16 v16 = qint16(value); + qint32 v32 = qint32(value); + + const auto hs8 = qHash(v8, seed); + const auto hs16 = qHash(v16, seed); + const auto hs32 = qHash(v32, seed); + const auto hs64 = qHash(value, seed); + + if (v8 == value) + QCOMPARE(hs8, hs32); + if (v16 == value) + QCOMPARE(hs16, hs32); + if (v32 == value) { + // because of QTBUG-116080, this may not match, but we can't guarantee + // it mismatches 100% of the time either + if constexpr (sizeof(size_t) > sizeof(int) || QT_VERSION_MAJOR > 6) + QCOMPARE(hs64, hs32); + } + +#if QT_SUPPORTS_INT128 + const auto hs128 = qHash(qint128(value), seed); + QCOMPARE(hs128, hs64); +#endif + + if (value > 0) { + quint64 u64 = quint64(value); + const auto hu64 = qHash(u64, seed); + QCOMPARE(hu64, hs64); + ::unsignedIntegerConsistency(u64, seed); + // by A == B && B == C -> A == C, we've shown hsXX == huXX for all XX + } +} + +void tst_QHashFunctions::extendedIntegerConsistency() { - QFETCH_GLOBAL(uint, seedValue); - seed = seedValue; +#ifdef QT_SUPPORTS_INT128 + // We only need to check qint128 and quint128 consistency here. + qint128 v65bit = Q_INT128_C(0x1'abea'06b7'dcf5'106a); + qint128 v127bit = Q_INT128_C(0x387c'ac7a'22a0'5242'9ee9'bcaa'6a53'13af); + + QCOMPARE(qHash(quint128(v65bit), seed), qHash(v65bit, seed)); + QCOMPARE(qHash(quint128(v127bit), seed), qHash(v127bit, seed)); +#else + QSKIP("This platform does not support extended integer types."); +#endif +} + +void tst_QHashFunctions::floatingPointConsistency_data() +{ + QTest::addColumn<double>("value"); + QTest::addRow("zero") << 0.0; + + QTest::addRow("1.0") << 1.0; + QTest::addRow("infinity") << std::numeric_limits<double>::infinity(); + + QTest::addRow("fp16_epsilon") << double(std::numeric_limits<qfloat16>::epsilon()); + QTest::addRow("fp16_min") << double(std::numeric_limits<qfloat16>::min()); + QTest::addRow("fp16_max") << double(std::numeric_limits<qfloat16>::max()); + + QTest::addRow("float_epsilon") << double(std::numeric_limits<float>::epsilon()); + QTest::addRow("float_min") << double(std::numeric_limits<float>::min()); + QTest::addRow("float_max") << double(std::numeric_limits<float>::max()); + + QTest::addRow("double_epsilon") << double(std::numeric_limits<double>::epsilon()); + QTest::addRow("double_min") << double(std::numeric_limits<double>::min()); + QTest::addRow("double_max") << double(std::numeric_limits<double>::max()); +} + +void tst_QHashFunctions::floatingPointConsistency() +{ + QFETCH(double, value); + long double lvalue = value; + float fp32 = float(value); + qfloat16 fp16 = qfloat16(value); + + const auto hfld = qHash(lvalue, seed); + const auto hf64 = qHash(value, seed); + const auto hf32 = qHash(fp32, seed); + const auto hf16 = qHash(fp16, seed); + + const auto hnfld = qHash(-lvalue, seed); + const auto hnf64 = qHash(-value, seed); + const auto hnf32 = qHash(-fp32, seed); + const auto hnf16 = qHash(-fp16, seed); + + if (fp16 == fp32) { + QCOMPARE(hf16, hf32); + QCOMPARE(hnf16, hnf32); + } + + // See QTBUG-116077; the rest isn't guaranteed to match (but we can't + // guarantee it will mismatch either). + return; + + if (fp32 == value) { + QCOMPARE(hf32, hf64); + QCOMPARE(hnf32, hnf64); + } + + QCOMPARE(hfld, hf64); + QCOMPARE(hnfld, hnf64); +} + +void tst_QHashFunctions::stringConsistency_data() +{ + QTest::addColumn<QString>("value"); + QTest::newRow("null") << QString(); + QTest::newRow("empty") << ""; + QTest::newRow("withnull") << QStringLiteral("A\0z"); + QTest::newRow("short-ascii") << "Hello"; // 10 bytes + QTest::newRow("medium-ascii") << "Hello, World"; // 24 bytes + QTest::newRow("long-ascii") << QStringLiteral("abcdefghijklmnopqrstuvxyz").repeated(16); + + QTest::newRow("short-latin1") << "Bokmål"; + QTest::newRow("medium-latin1") << "Det går bra!"; // 24 bytes + QTest::newRow("long-latin1") + << R"(Alle mennesker er født frie og med samme menneskeverd og menneskerettigheter. + De er utstyrt med fornuft og samvittighet og bør handle mot hverandre i brorskapets ånd.)"; + + QTest::newRow("short-nonlatin1") << "Ελληνικά"; + QTest::newRow("long-nonlatin1") + << R"('Ολοι οι άνθρωποι γεννιούνται ελεύθεροι και ίσοι στην αξιοπρέπεια και τα + δικαιώματα. Είναι προικισμένοι με λογική και συνείδηση, και οφείλουν να συμπεριφέρονται μεταξύ + τους με πνεύμα αδελφοσύνης.)"; +} + +void tst_QHashFunctions::stringConsistency() +{ + QFETCH(QString, value); + QStringView sv = value; + QByteArray u8ba = value.toUtf8(); + QByteArray u8bav = u8ba; + + // sanity checking: + QCOMPARE(sv.isNull(), value.isNull()); + QCOMPARE(sv.isEmpty(), value.isEmpty()); + QCOMPARE(u8ba.isNull(), value.isNull()); + QCOMPARE(u8ba.isEmpty(), value.isEmpty()); + QCOMPARE(u8bav.isNull(), value.isNull()); + QCOMPARE(u8bav.isEmpty(), value.isEmpty()); + + QCOMPARE(qHash(sv, seed), qHash(value, seed)); + QCOMPARE(qHash(u8bav, seed), qHash(u8ba, seed)); + + if (seed == 0 || QHashHeterogeneousSearch<QString, QLatin1StringView>::value) { + QByteArray l1ba = value.toLatin1(); + QLatin1StringView l1sv(l1ba.data(), l1ba.size()); +#ifdef Q_PROCESSOR_ARM + // zero-extending aeshash not implemented on ARM +#else + if (value == l1sv) + QCOMPARE(qHash(l1sv, seed), qHash(value, seed)); +#endif + } } void tst_QHashFunctions::qhash() @@ -180,9 +436,7 @@ void tst_QHashFunctions::qhash_of_zero_floating_points() { QCOMPARE(qHash(-0.0f, seed), qHash(0.0f, seed)); QCOMPARE(qHash(-0.0 , seed), qHash(0.0 , seed)); -#ifndef Q_OS_DARWIN QCOMPARE(qHash(-0.0L, seed), qHash(0.0L, seed)); -#endif } void tst_QHashFunctions::qthash_data() @@ -352,13 +606,9 @@ void tst_QHashFunctions::stdPair_template(const T1 &t1, const T2 &t2) std::pair<T1, T2> dpair{}; std::pair<T1, T2> vpair{t1, t2}; - size_t seed = QHashSeed::globalSeed(); - // confirm proper working of the pair and of the underlying types QVERIFY(t1 == t1); QVERIFY(t2 == t2); - QCOMPARE(qHash(t1), qHash(t1)); - QCOMPARE(qHash(t2), qHash(t2)); QCOMPARE(qHash(t1, seed), qHash(t1, seed)); QCOMPARE(qHash(t2, seed), qHash(t2, seed)); @@ -366,12 +616,21 @@ void tst_QHashFunctions::stdPair_template(const T1 &t1, const T2 &t2) QVERIFY(vpair == vpair); // therefore their hashes should be equal - QCOMPARE(qHash(dpair), qHash(dpair)); QCOMPARE(qHash(dpair, seed), qHash(dpair, seed)); - QCOMPARE(qHash(vpair), qHash(vpair)); QCOMPARE(qHash(vpair, seed), qHash(vpair, seed)); } +void tst_QHashFunctions::enum_int_consistent_hash_qtbug108032() +{ + enum E { E1, E2, E3 }; + + static_assert(QHashPrivate::HasQHashSingleArgOverload<E>); + + QCOMPARE(qHash(E1, seed), qHash(int(E1), seed)); + QCOMPARE(qHash(E2, seed), qHash(int(E2), seed)); + QCOMPARE(qHash(E3, seed), qHash(int(E3), seed)); +} + #if QT_DEPRECATED_SINCE(6, 6) void tst_QHashFunctions::setGlobalQHashSeed() { diff --git a/tests/auto/corelib/tools/qhashseed/CMakeLists.txt b/tests/auto/corelib/tools/qhashseed/CMakeLists.txt index a098f103a7..27b4cce133 100644 --- a/tests/auto/corelib/tools/qhashseed/CMakeLists.txt +++ b/tests/auto/corelib/tools/qhashseed/CMakeLists.txt @@ -5,6 +5,12 @@ ## tst_qhashseed Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qhashseed LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qhashseed SOURCES tst_qhashseed.cpp diff --git a/tests/auto/corelib/tools/qhashseed/tst_qhashseed.cpp b/tests/auto/corelib/tools/qhashseed/tst_qhashseed.cpp index 2562ebfaa6..99fc7c5772 100644 --- a/tests/auto/corelib/tools/qhashseed/tst_qhashseed.cpp +++ b/tests/auto/corelib/tools/qhashseed/tst_qhashseed.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/tools/qhashseed/tst_qhashseed_helper.cpp b/tests/auto/corelib/tools/qhashseed/tst_qhashseed_helper.cpp index 57ecf09575..25e7909870 100644 --- a/tests/auto/corelib/tools/qhashseed/tst_qhashseed_helper.cpp +++ b/tests/auto/corelib/tools/qhashseed/tst_qhashseed_helper.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qhashfunctions.h> #include <stdio.h> diff --git a/tests/auto/corelib/tools/qline/CMakeLists.txt b/tests/auto/corelib/tools/qline/CMakeLists.txt index 339d2238d4..17a3a1bcef 100644 --- a/tests/auto/corelib/tools/qline/CMakeLists.txt +++ b/tests/auto/corelib/tools/qline/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qline.pro. - ##################################################################### ## tst_qline Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qline LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qline SOURCES tst_qline.cpp diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp index dd7bb2b997..51f1f8ac79 100644 --- a/tests/auto/corelib/tools/qline/tst_qline.cpp +++ b/tests/auto/corelib/tools/qline/tst_qline.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <qline.h> diff --git a/tests/auto/corelib/tools/qlist/CMakeLists.txt b/tests/auto/corelib/tools/qlist/CMakeLists.txt index 30751c7bac..fdcfcd7424 100644 --- a/tests/auto/corelib/tools/qlist/CMakeLists.txt +++ b/tests/auto/corelib/tools/qlist/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qlist.pro. - ##################################################################### ## tst_qlist Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlist LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qlist SOURCES tst_qlist.cpp diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index e797b76f69..35d69e8433 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -1,15 +1,15 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QAtomicInt> #include <QThread> #include <QSemaphore> -#include <private/qatomicscopedvaluerollback_p.h> +#include <QAtomicScopedValueRollback> #include <qlist.h> -#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) +#ifdef QT_COMPILER_HAS_LWG3346 # if __has_include(<concepts>) # include <concepts> # if defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L @@ -231,6 +231,16 @@ private slots: void appendCustom() const { append<Custom>(); } void appendRvalue() const; void appendList() const; + void assignEmpty() const; + void assignInt() const { assign<int>(); } + void assignMovable() const { assign<Movable>(); } + void assignCustom() const { assign<Custom>(); } + void assignUsesPrependBuffer_int_data() { assignUsesPrependBuffer_data(); } + void assignUsesPrependBuffer_int() const { assignUsesPrependBuffer<int>(); } + void assignUsesPrependBuffer_Movable_data() { assignUsesPrependBuffer_data(); } + void assignUsesPrependBuffer_Movable() const { assignUsesPrependBuffer<Movable>(); } + void assignUsesPrependBuffer_Custom_data() { assignUsesPrependBuffer_data(); } + void assignUsesPrependBuffer_Custom() const { assignUsesPrependBuffer<Custom>(); } void at() const; void capacityInt() const { capacity<int>(); } void capacityMovable() const { capacity<Movable>(); } @@ -312,6 +322,7 @@ private slots: void resizeToZero() const; void resizeToTheSameSize_data(); void resizeToTheSameSize() const; + void resizeForOverwrite() const; void iterators() const; void constIterators() const; void reverseIterators() const; @@ -396,6 +407,9 @@ private: template<typename T> void testAssignment() const; template<typename T> void add() const; template<typename T> void append() const; + template<typename T> void assign() const; + void assignUsesPrependBuffer_data() const; + template<typename T> void assignUsesPrependBuffer() const; template<typename T> void assignFromInitializerList() const; template<typename T> void capacity() const; template<typename T> void clear() const; @@ -548,25 +562,22 @@ void tst_QList::constructors_reserveAndInitialize() const { // default-initialise items - QList<int> myInt(5, 42); + const QList<int> myInt(5, 42); QVERIFY(myInt.capacity() == 5); - foreach (int meaningoflife, myInt) { + for (int meaningoflife : myInt) QCOMPARE(meaningoflife, 42); - } - QList<QString> myString(5, QString::fromLatin1("c++")); + const QList<QString> myString(5, QString::fromLatin1("c++")); QVERIFY(myString.capacity() == 5); // make sure all items are initialised ok - foreach (QString meaningoflife, myString) { + for (const QString &meaningoflife : myString) QCOMPARE(meaningoflife, QString::fromLatin1("c++")); - } - QList<Custom> myCustom(5, Custom('n')); + const QList<Custom> myCustom(5, Custom('n')); QVERIFY(myCustom.capacity() == 5); // make sure all items are initialised ok - foreach (Custom meaningoflife, myCustom) { + for (Custom meaningoflife : myCustom) QCOMPARE(meaningoflife.i, 'n'); - } } template<typename T> @@ -750,6 +761,162 @@ void tst_QList::append() const } } +void tst_QList::assignEmpty() const +{ + // Test that the realloc branch in assign(it, it) doesn't crash. + using T = int; + QList<T> list; + QList<T> ref1 = list; + QVERIFY(list.d.needsDetach()); + list.assign(list.begin(), list.begin()); + +#if !defined Q_OS_QNX // QNX has problems with the empty istream_iterator + auto empty = std::istream_iterator<T>{}; + list.squeeze(); + QCOMPARE_EQ(list.capacity(), 0); + ref1 = list; + QVERIFY(list.d.needsDetach()); + list.assign(empty, empty); +#endif +} + +template <typename T> +void tst_QList::assign() const +{ + TST_QLIST_CHECK_LEAKS(T) + { + QList<T> myvec; + myvec.assign(2, T_FOO); + QVERIFY(myvec.isDetached()); + QCOMPARE(myvec, QList<T>() << T_FOO << T_FOO); + + QList<T> myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + myvec.assign(3, T_BAR); + QCOMPARE(myvec, QList<T>() << T_BAR << T_BAR << T_BAR); + QVERIFY(myvec.isDetached()); + QVERIFY(myvecCopy.isDetached()); + QVERIFY(!myvec.isSharedWith(myvecCopy)); + QVERIFY(!myvecCopy.isSharedWith(myvec)); + } + { + QList<T> myvec; + myvec.assign(4, T_FOO); + QVERIFY(myvec.isDetached()); + QCOMPARE(myvec, QList<T>() << T_FOO << T_FOO << T_FOO << T_FOO); + + QList<T> myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + myvecCopy.assign(myvec.begin(), myvec.begin() + 2); + QVERIFY(myvec.isDetached()); + QVERIFY(myvecCopy.isDetached()); + QVERIFY(!myvec.isSharedWith(myvecCopy)); + QVERIFY(!myvecCopy.isSharedWith(myvec)); + QCOMPARE(myvecCopy, QList<T>() << T_FOO << T_FOO); + } +} + +inline namespace Scenarios { +Q_NAMESPACE +enum ListState { + UnsharedList, + SharedList, +}; +Q_ENUM_NS(ListState) +enum RelationWithPrependBuffer { + FitsIntoFreeSpaceAtBegin, + FitsFreeSpaceAtBeginExactly, + ExceedsFreeSpaceAtBegin, + FitsFreeSpaceAtBeginPlusSizeExactly, + FullCapacity, +}; +Q_ENUM_NS(RelationWithPrependBuffer) +} // namespace Scenarios + +void tst_QList::assignUsesPrependBuffer_data() const +{ + QTest::addColumn<ListState>("listState"); + QTest::addColumn<RelationWithPrependBuffer>("relationWithPrependBuffer"); + + const auto sme = QMetaEnum::fromType<ListState>(); + const auto rme = QMetaEnum::fromType<RelationWithPrependBuffer>(); + + for (int i = 0, s = sme.value(i); s != -1; s = sme.value(++i)) { + for (int j = 0, r = rme.value(j); r != -1; r = rme.value(++j)) { + QTest::addRow("%s-%s", sme.key(i), rme.key(j)) + << ListState(s) << RelationWithPrependBuffer(r); + } + } +} + +template <typename T> +void tst_QList::assignUsesPrependBuffer() const +{ + QFETCH(const ListState, listState); + QFETCH(const RelationWithPrependBuffer, relationWithPrependBuffer); + + const auto capBegin = [](const QList<T> &l) { + return l.begin() - l.d.freeSpaceAtBegin(); + }; + const auto capEnd = [](const QList<T> &l) { + return l.end() + l.d.freeSpaceAtEnd(); + }; + + TST_QLIST_CHECK_LEAKS(T) + { + // Test the prepend optimization. + QList<T> withFreeSpaceAtBegin(16, T_FOO); + // try at most 100 times to create freeSpaceAtBegin(): + for (int i = 0; i < 100 && withFreeSpaceAtBegin.d.freeSpaceAtBegin() < 2; ++i) + withFreeSpaceAtBegin.prepend(T_FOO); + QCOMPARE_GT(withFreeSpaceAtBegin.d.freeSpaceAtBegin(), 1); + + auto c = [&] { + switch (listState) { + case UnsharedList: return std::move(withFreeSpaceAtBegin); + case SharedList: return withFreeSpaceAtBegin; + } + Q_UNREACHABLE_RETURN(withFreeSpaceAtBegin); + }(); + + const auto n = [&] () -> qsizetype { + switch (relationWithPrependBuffer) { + case FitsIntoFreeSpaceAtBegin: + return qsizetype(1); + case FitsFreeSpaceAtBeginExactly: + return c.d.freeSpaceAtBegin(); + case ExceedsFreeSpaceAtBegin: + return c.d.freeSpaceAtBegin() + 1; + case FitsFreeSpaceAtBeginPlusSizeExactly: + return c.d.freeSpaceAtBegin() + c.size(); + case FullCapacity: + return c.capacity(); + }; + Q_UNREACHABLE_RETURN(0); + }(); + + const auto oldCapBegin = capBegin(c); + const auto oldCapEnd = capEnd(c); + + const std::vector v(n, T_BAR); + c.assign(v.begin(), v.end()); + QCOMPARE_EQ(c.d.freeSpaceAtBegin(), 0); // we used the prepend-buffer + if (listState != SharedList) { + // check that we didn't reallocate + QCOMPARE_EQ(capBegin(c), oldCapBegin); + QCOMPARE_EQ(capEnd(c), oldCapEnd); + } + } +} + void tst_QList::appendRvalue() const { QList<QString> v; @@ -941,6 +1108,7 @@ void tst_QList::appendList() const // Using operators // << QList<ConstructionCounted> v6; + v6.reserve(4); v6 << (QList<ConstructionCounted>() << 1 << 2); v6 << (QList<ConstructionCounted>() << 3 << 4); QCOMPARE(v6, expectedFour); @@ -1078,20 +1246,20 @@ void tst_QList::count() const { // zero size QList<T> myvec; - QVERIFY(myvec.count() == 0); + QVERIFY(myvec.size() == 0); QVERIFY(!myvec.isDetached()); // grow myvec.append(SimpleValue<T>::at(0)); - QVERIFY(myvec.count() == 1); + QVERIFY(myvec.size() == 1); myvec.append(SimpleValue<T>::at(1)); - QVERIFY(myvec.count() == 2); + QVERIFY(myvec.size() == 2); // shrink myvec.remove(0); - QVERIFY(myvec.count() == 1); + QVERIFY(myvec.size() == 1); myvec.remove(0); - QVERIFY(myvec.count() == 0); + QVERIFY(myvec.size() == 0); } // count of items @@ -1905,11 +2073,11 @@ void tst_QList::move() const list << T_FOO << T_BAR << T_BAZ; // move an item - list.move(0, list.count() - 1); + list.move(0, list.size() - 1); QCOMPARE(list, QList<T>() << T_BAR << T_BAZ << T_FOO); // move it back - list.move(list.count() - 1, 0); + list.move(list.size() - 1, 0); QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ); // move an item in the middle @@ -2364,6 +2532,51 @@ void tst_QList::resizeToTheSameSize() const QCOMPARE(y.size(), x.size()); } +void tst_QList::resizeForOverwrite() const +{ + constexpr int BUILD_COUNT = 42; + { + // Smoke test + QList<int> l(BUILD_COUNT, Qt::Uninitialized); + l.resizeForOverwrite(l.size() + BUILD_COUNT); + } + + { + const int beforeCounter = Movable::counter.loadRelaxed(); + QList<Movable> l(BUILD_COUNT, Qt::Uninitialized); + const int after1Counter = Movable::counter.loadRelaxed(); + QCOMPARE(after1Counter, beforeCounter + BUILD_COUNT); + + l.resizeForOverwrite(l.size() + BUILD_COUNT); + const int after2Counter = Movable::counter.loadRelaxed(); + QCOMPARE(after2Counter, after1Counter + BUILD_COUNT); + } + + struct QtInitializationSupport { + bool wasInitialized; + QtInitializationSupport() : wasInitialized(true) {} + explicit QtInitializationSupport(Qt::Initialization) : wasInitialized(false) {} + }; + + { + QList<QtInitializationSupport> l(BUILD_COUNT); + for (const auto &elem : l) + QVERIFY(elem.wasInitialized); + l.resize(l.size() + BUILD_COUNT); + for (const auto &elem : l) + QVERIFY(elem.wasInitialized); + } + + { + QList<QtInitializationSupport> l(BUILD_COUNT, Qt::Uninitialized); + for (const auto &elem : l) + QVERIFY(!elem.wasInitialized); + l.resizeForOverwrite(l.size() + BUILD_COUNT); + for (const auto &elem : l) + QVERIFY(!elem.wasInitialized); + } +} + void tst_QList::iterators() const { QList<int> v; @@ -2673,24 +2886,24 @@ void tst_QList::size() const // zero size QList<T> myvec; QVERIFY(myvec.size() == 0); - QCOMPARE(myvec.length(), myvec.size()); + QCOMPARE(myvec.size(), myvec.size()); QVERIFY(!myvec.isDetached()); // grow myvec.append(SimpleValue<T>::at(0)); QVERIFY(myvec.size() == 1); - QCOMPARE(myvec.length(), myvec.size()); + QCOMPARE(myvec.size(), myvec.size()); myvec.append(SimpleValue<T>::at(1)); QVERIFY(myvec.size() == 2); - QCOMPARE(myvec.length(), myvec.size()); + QCOMPARE(myvec.size(), myvec.size()); // shrink myvec.remove(0); QVERIFY(myvec.size() == 1); - QCOMPARE(myvec.length(), myvec.size()); + QCOMPARE(myvec.size(), myvec.size()); myvec.remove(0); QVERIFY(myvec.size() == 0); - QCOMPARE(myvec.length(), myvec.size()); + QCOMPARE(myvec.size(), myvec.size()); } // ::squeeze() is tested in ::capacity(). @@ -3613,7 +3826,7 @@ void tst_QList::stability_append() const std::generate(v.begin(), v.end(), [&k]() { return SimpleValue<T>::at(k++); }); QList<T> src(1, SimpleValue<T>::at(0)); v.append(src.begin(), src.end()); - QVERIFY(v.size() < v.capacity()); + QCOMPARE_LE(v.size(), v.capacity()); for (int i = 0; i < v.capacity() - v.size(); ++i) { auto [copy, reference] = qlistCopyAndReferenceFromRange(v.begin(), v.end()); diff --git a/tests/auto/corelib/tools/qmacautoreleasepool/CMakeLists.txt b/tests/auto/corelib/tools/qmacautoreleasepool/CMakeLists.txt index 15c89e18fb..b968945ac6 100644 --- a/tests/auto/corelib/tools/qmacautoreleasepool/CMakeLists.txt +++ b/tests/auto/corelib/tools/qmacautoreleasepool/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qmacautoreleasepool.pro. - ##################################################################### ## tst_qmacautoreleasepool Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmacautoreleasepool LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmacautoreleasepool SOURCES tst_qmacautoreleasepool.mm diff --git a/tests/auto/corelib/tools/qmacautoreleasepool/tst_qmacautoreleasepool.mm b/tests/auto/corelib/tools/qmacautoreleasepool/tst_qmacautoreleasepool.mm index e18d848f87..e7923b47f3 100644 --- a/tests/auto/corelib/tools/qmacautoreleasepool/tst_qmacautoreleasepool.mm +++ b/tests/auto/corelib/tools/qmacautoreleasepool/tst_qmacautoreleasepool.mm @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -14,7 +14,6 @@ private slots: void noPool(); void rootLevelPool(); void stackAllocatedPool(); - void heapAllocatedPool(); }; static id lastDeallocedObject = nil; @@ -63,26 +62,6 @@ void tst_QMacAutoreleasePool::stackAllocatedPool() [pool drain]; } -void tst_QMacAutoreleasePool::heapAllocatedPool() -{ - // The special case, a pool allocated on the heap, or as a member of a - // heap allocated object. This is not a supported use of QMacAutoReleasePool, - // and will result in warnings if the pool is prematurely drained. - - NSObject *allocedObject = nil; - { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - QMacAutoReleasePool *qtPool = nullptr; - { - qtPool = new QMacAutoReleasePool; - allocedObject = [[[DeallocTracker alloc] init] autorelease]; - } - [pool drain]; - delete qtPool; - } - QCOMPARE(lastDeallocedObject, allocedObject); -} - QTEST_APPLESS_MAIN(tst_QMacAutoreleasePool) #include "tst_qmacautoreleasepool.moc" diff --git a/tests/auto/corelib/tools/qmakearray/CMakeLists.txt b/tests/auto/corelib/tools/qmakearray/CMakeLists.txt index 7af188c27a..cec589628f 100644 --- a/tests/auto/corelib/tools/qmakearray/CMakeLists.txt +++ b/tests/auto/corelib/tools/qmakearray/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qmakearray.pro. - ##################################################################### ## tst_qmakearray Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmakearray LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmakearray SOURCES tst_qmakearray.cpp diff --git a/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp b/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp index ffd99a0309..1d796452b0 100644 --- a/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp +++ b/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/tools/qmap/CMakeLists.txt b/tests/auto/corelib/tools/qmap/CMakeLists.txt index 6338657943..bddf9267f8 100644 --- a/tests/auto/corelib/tools/qmap/CMakeLists.txt +++ b/tests/auto/corelib/tools/qmap/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qmap.pro. - ##################################################################### ## tst_qmap Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmap LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmap SOURCES tst_qmap.cpp diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index d4f886784d..6950dcf705 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -1,9 +1,13 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qmap.h> #include <QTest> + #include <QDebug> +#include <QScopeGuard> + +using namespace Qt::StringLiterals; QT_WARNING_DISABLE_DEPRECATED @@ -61,6 +65,8 @@ private slots: void removeElementsInMap(); void toStdMap(); + void multiMapStoresInReverseInsertionOrder(); + // Tests for deprecated APIs. #if QT_DEPRECATED_SINCE(6, 0) void deprecatedInsertMulti(); @@ -166,8 +172,8 @@ void tst_QMap::count() { MyMap map; MyMap map2( map ); - QCOMPARE( map.count(), 0 ); - QCOMPARE( map2.count(), 0 ); + QCOMPARE( map.size(), 0 ); + QCOMPARE( map2.size(), 0 ); QCOMPARE( MyClass::count, int(0) ); QCOMPARE(map.count("key"), 0); QCOMPARE(map.size(), 0); @@ -176,9 +182,9 @@ void tst_QMap::count() QVERIFY(!map2.isDetached()); // detach map2["Hallo"] = MyClass( "Fritz" ); - QCOMPARE( map.count(), 0 ); QCOMPARE( map.size(), 0 ); - QCOMPARE( map2.count(), 1 ); + QCOMPARE( map.size(), 0 ); + QCOMPARE( map2.size(), 1 ); QCOMPARE( map2.size(), 1 ); QVERIFY(!map.isDetached()); #ifndef Q_CC_SUN @@ -190,11 +196,11 @@ void tst_QMap::count() { typedef QMap<QString, MyClass> Map; Map map; - QCOMPARE( map.count(), 0); + QCOMPARE( map.size(), 0); map.insert( "Torben", MyClass("Weis") ); - QCOMPARE( map.count(), 1 ); + QCOMPARE( map.size(), 1 ); map.insert( "Claudia", MyClass("Sorg") ); - QCOMPARE( map.count(), 2 ); + QCOMPARE( map.size(), 2 ); map.insert( "Lars", MyClass("Linzbach") ); map.insert( "Matthias", MyClass("Ettrich") ); map.insert( "Sue", MyClass("Paludo") ); @@ -202,7 +208,7 @@ void tst_QMap::count() map.insert( "Haavard", MyClass("Nord") ); map.insert( "Arnt", MyClass("Gulbrandsen") ); map.insert( "Paul", MyClass("Tvete") ); - QCOMPARE( map.count(), 9 ); + QCOMPARE( map.size(), 9 ); map.insert( "Paul", MyClass("Tvete 1") ); map.insert( "Paul", MyClass("Tvete 2") ); map.insert( "Paul", MyClass("Tvete 3") ); @@ -210,69 +216,69 @@ void tst_QMap::count() map.insert( "Paul", MyClass("Tvete 5") ); map.insert( "Paul", MyClass("Tvete 6") ); - QCOMPARE( map.count(), 9 ); + QCOMPARE( map.size(), 9 ); QCOMPARE( map.count("Paul"), 1 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif Map map2( map ); - QVERIFY( map2.count() == 9 ); + QVERIFY( map2.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2.insert( "Kay", MyClass("Roemer") ); - QVERIFY( map2.count() == 10 ); - QVERIFY( map.count() == 9 ); + QVERIFY( map2.size() == 10 ); + QVERIFY( map.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 19 ); #endif map2 = map; - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 9 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2.insert( "Kay", MyClass("Roemer") ); - QVERIFY( map2.count() == 10 ); + QVERIFY( map2.size() == 10 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 19 ); #endif map2.clear(); - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2 = map; - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 9 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 9 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map2.clear(); - QVERIFY( map.count() == 9 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 9 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 9 ); #endif map.remove( "Lars" ); - QVERIFY( map.count() == 8 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 8 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 8 ); #endif map.remove( "Mist" ); - QVERIFY( map.count() == 8 ); - QVERIFY( map2.count() == 0 ); + QVERIFY( map.size() == 8 ); + QVERIFY( map2.size() == 0 ); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 8 ); #endif @@ -286,22 +292,22 @@ void tst_QMap::count() #ifndef Q_CC_SUN QVERIFY( MyClass::count == 1 ); #endif - QVERIFY( map.count() == 1 ); + QVERIFY( map.size() == 1 ); (void)map["Torben"].str; (void)map["Lars"].str; #ifndef Q_CC_SUN QVERIFY( MyClass::count == 2 ); #endif - QVERIFY( map.count() == 2 ); + QVERIFY( map.size() == 2 ); const Map& cmap = map; (void)cmap["Depp"].str; #ifndef Q_CC_SUN QVERIFY( MyClass::count == 2 ); #endif - QVERIFY( map.count() == 2 ); - QVERIFY( cmap.count() == 2 ); + QVERIFY( map.size() == 2 ); + QVERIFY( cmap.size() == 2 ); } QCOMPARE( MyClass::count, 0 ); { @@ -318,8 +324,8 @@ void tst_QMap::count() { QMultiMap<int, MyClass> map; QMultiMap<int, MyClass> map2(map); - QCOMPARE(map.count(), 0); - QCOMPARE(map2.count(), 0); + QCOMPARE(map.size(), 0); + QCOMPARE(map2.size(), 0); QCOMPARE(MyClass::count, 0); QCOMPARE(map.count(1), 0); QCOMPARE(map.size(), 0); @@ -329,26 +335,26 @@ void tst_QMap::count() // detach map2.insert(0, MyClass("value0")); - QCOMPARE(map.count(), 0); QCOMPARE(map.size(), 0); - QCOMPARE(map2.count(), 1); + QCOMPARE(map.size(), 0); + QCOMPARE(map2.size(), 1); QCOMPARE(map2.size(), 1); QVERIFY(!map.isDetached()); QCOMPARE(MyClass::count, 1); map2.insert(1, MyClass("value1")); map2.insert(2, MyClass("value2")); - QCOMPARE(map2.count(), 3); + QCOMPARE(map2.size(), 3); QCOMPARE(MyClass::count, 3); map2.insert(0, MyClass("value0_1")); map2.insert(0, MyClass("value0_2")); - QCOMPARE(map2.count(), 5); + QCOMPARE(map2.size(), 5); QCOMPARE(map2.count(0), 3); QCOMPARE(MyClass::count, 5); map2.clear(); - QCOMPARE(map2.count(), 0); + QCOMPARE(map2.size(), 0); QCOMPARE(MyClass::count, 0); } @@ -634,16 +640,19 @@ void tst_QMap::operator_eq() QMap<int, int> b; QVERIFY(a == b); + QCOMPARE(qHash(a), qHash(b)); QVERIFY(!(a != b)); a.insert(1,1); b.insert(1,1); QVERIFY(a == b); + QCOMPARE(qHash(a), qHash(b)); QVERIFY(!(a != b)); a.insert(0,1); b.insert(0,1); QVERIFY(a == b); + QCOMPARE(qHash(a), qHash(b)); QVERIFY(!(a != b)); // compare for inequality: @@ -666,6 +675,7 @@ void tst_QMap::operator_eq() QMap<QString, QString> b; QVERIFY(a == b); + QCOMPARE(qHash(a), qHash(b)); QVERIFY(!(a != b)); a.insert("Hello", "World"); @@ -674,6 +684,7 @@ void tst_QMap::operator_eq() b.insert("Hello", "World"); QVERIFY(a == b); + QCOMPARE(qHash(a), qHash(b)); QVERIFY(!(a != b)); a.insert("Goodbye", "cruel world"); @@ -690,6 +701,7 @@ void tst_QMap::operator_eq() // empty keys and null keys match: b.insert(QString(""), QString()); QVERIFY(a == b); + QCOMPARE(qHash(a), qHash(b)); QVERIFY(!(a != b)); } @@ -1589,26 +1601,26 @@ void tst_QMap::qmultimap_specific() } QVERIFY(map1.contains(9, 99)); - QCOMPARE(map1.count(), 45); + QCOMPARE(map1.size(), 45); map1.remove(9, 99); QVERIFY(!map1.contains(9, 99)); - QCOMPARE(map1.count(), 44); + QCOMPARE(map1.size(), 44); map1.remove(9, 99); QVERIFY(!map1.contains(9, 99)); - QCOMPARE(map1.count(), 44); + QCOMPARE(map1.size(), 44); map1.remove(1, 99); - QCOMPARE(map1.count(), 44); + QCOMPARE(map1.size(), 44); map1.insert(1, 99); map1.insert(1, 99); - QCOMPARE(map1.count(), 46); + QCOMPARE(map1.size(), 46); map1.remove(1, 99); - QCOMPARE(map1.count(), 44); + QCOMPARE(map1.size(), 44); map1.remove(1, 99); - QCOMPARE(map1.count(), 44); + QCOMPARE(map1.size(), 44); { QMultiMap<int, int>::const_iterator i = map1.constFind(1, 11); @@ -1667,7 +1679,7 @@ void tst_QMap::qmultimap_specific() map2.insert(42, 1); map2.insert(10, 2); map2.insert(48, 3); - QCOMPARE(map1.count(), map2.count()); + QCOMPARE(map1.size(), map2.size()); QVERIFY(map1.remove(42,5)); QVERIFY(map2.remove(42,5)); QVERIFY(map1 == map2); @@ -1802,19 +1814,13 @@ void tst_QMap::equal_range() QCOMPARE(map.count(1), 2); } -template <class T> -const T &const_(const T &t) -{ - return t; -} - void tst_QMap::insert() { QMap<QString, float> map; map.insert("cs/key1", 1); map.insert("cs/key2", 2); map.insert("cs/key1", 3); - QCOMPARE(map.count(), 2); + QCOMPARE(map.size(), 2); QMap<int, int> intMap; for (int i = 0; i < 1000; ++i) { @@ -1893,7 +1899,7 @@ void testDetachWhenInsert() QCOMPARE(source, referenceSource); QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } // copy insertion of shared map @@ -1917,7 +1923,7 @@ void testDetachWhenInsert() QCOMPARE(sourceCopy, referenceSource); QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } // move insertion of non-shared map @@ -1937,7 +1943,7 @@ void testDetachWhenInsert() dest.unite(source); // QMultiMap QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } // move insertion of shared map @@ -1960,7 +1966,7 @@ void testDetachWhenInsert() QCOMPARE(sourceCopy, referenceSource); QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } }; @@ -1991,7 +1997,7 @@ void tst_QMap::insertMap() map.insert(map2); - QCOMPARE(map.count(), 5); + QCOMPARE(map.size(), 5); for (int i = 0; i < 5; ++i) QCOMPARE(map[i], i); } @@ -2006,7 +2012,7 @@ void tst_QMap::insertMap() map.insert(map2); - QCOMPARE(map.count(), 17); + QCOMPARE(map.size(), 17); for (int i = 0; i < 10; ++i) { // i * 3 == i except for i = 4, 8 QCOMPARE(map[i * 3], (i && i % 4 == 0) ? i - (i / 4) : i); @@ -2028,7 +2034,7 @@ void tst_QMap::insertMap() QMap<int, int> map2; map.insert(map2); - QCOMPARE(map.count(), 1); + QCOMPARE(map.size(), 1); QCOMPARE(map[1], 1); } { @@ -2037,7 +2043,7 @@ void tst_QMap::insertMap() map2.insert(1, 1); map.insert(map2); - QCOMPARE(map.count(), 1); + QCOMPARE(map.size(), 1); QCOMPARE(map[1], 1); QMap<int, int> map3; @@ -2053,7 +2059,7 @@ void tst_QMap::insertMap() // Test inserting into self, nothing should happen map.insert(map); - QCOMPARE(map.count(), 3); + QCOMPARE(map.size(), 3); for (int i = 0; i < 3; ++i) QCOMPARE(map[i], i); } @@ -2071,7 +2077,7 @@ void tst_QMap::insertMap() map.insert(map2); - QCOMPARE(map.count(), 1); + QCOMPARE(map.size(), 1); } testDetachWhenInsert<QMap>(); @@ -2133,7 +2139,7 @@ void tst_QMap::checkMostLeftNode() void tst_QMap::initializerList() { QMap<int, QString> map = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}}; - QCOMPARE(map.count(), 2); + QCOMPARE(map.size(), 2); QCOMPARE(map[1], QString("hello")); QCOMPARE(map[2], QString("initializer_list")); @@ -2143,9 +2149,9 @@ void tst_QMap::initializerList() // QCOMPARE(stdm[1], QString("bar")); QMultiMap<QString, int> multiMap{{"il", 1}, {"il", 2}, {"il", 3}}; - QCOMPARE(multiMap.count(), 3); + QCOMPARE(multiMap.size(), 3); QList<int> values = multiMap.values("il"); - QCOMPARE(values.count(), 3); + QCOMPARE(values.size(), 3); QMap<int, int> emptyMap{}; QVERIFY(emptyMap.isEmpty()); @@ -2554,6 +2560,24 @@ void tst_QMap::toStdMap() toStdMapTestMethod<QMultiMap<int, QString>>(expectedMultiMap); } +void tst_QMap::multiMapStoresInReverseInsertionOrder() +{ + const QString strings[] = { + u"zero"_s, + u"null"_s, + u"nada"_s, + }; + { + QMultiMap<int, QString> map; + for (const QString &string : strings) + map.insert(0, string); + auto printOnFailure = qScopeGuard([&] { qDebug() << map; }); + QVERIFY(std::equal(map.begin(), map.end(), + std::rbegin(strings), std::rend(strings))); + printOnFailure.dismiss(); + } +} + #if QT_DEPRECATED_SINCE(6, 0) void tst_QMap::deprecatedInsertMulti() { diff --git a/tests/auto/corelib/tools/qmargins/CMakeLists.txt b/tests/auto/corelib/tools/qmargins/CMakeLists.txt index befeea0ba7..2e0ea797ff 100644 --- a/tests/auto/corelib/tools/qmargins/CMakeLists.txt +++ b/tests/auto/corelib/tools/qmargins/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qmargins.pro. - ##################################################################### ## tst_qmargins Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmargins LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmargins SOURCES tst_qmargins.cpp diff --git a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp index c99b3d6e33..2611f62f01 100644 --- a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp +++ b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp @@ -1,5 +1,34 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QMargins> +#ifdef QVARIANT_H +# error "This test requires qmargins.h to not include qvariant.h" +#endif + +// don't assume <type_traits> +template <typename T, typename U> +constexpr inline bool my_is_same_v = false; +template <typename T> +constexpr inline bool my_is_same_v<T, T> = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v<decltype(get<0>(std::declval<QMargins cvref >())), int cvref >); \ + static_assert(my_is_same_v<decltype(get<1>(std::declval<QMargins cvref >())), int cvref >); \ + static_assert(my_is_same_v<decltype(get<2>(std::declval<QMargins cvref >())), int cvref >); \ + static_assert(my_is_same_v<decltype(get<3>(std::declval<QMargins cvref >())), int cvref >); \ + \ + static_assert(my_is_same_v<decltype(get<0>(std::declval<QMarginsF cvref >())), qreal cvref >); \ + static_assert(my_is_same_v<decltype(get<1>(std::declval<QMarginsF cvref >())), qreal cvref >); \ + static_assert(my_is_same_v<decltype(get<2>(std::declval<QMarginsF cvref >())), qreal cvref >); \ + static_assert(my_is_same_v<decltype(get<3>(std::declval<QMarginsF cvref >())), qreal cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK #include <QTest> #include <qmargins.h> diff --git a/tests/auto/corelib/tools/qmessageauthenticationcode/CMakeLists.txt b/tests/auto/corelib/tools/qmessageauthenticationcode/CMakeLists.txt index db3062100a..a21481b7ba 100644 --- a/tests/auto/corelib/tools/qmessageauthenticationcode/CMakeLists.txt +++ b/tests/auto/corelib/tools/qmessageauthenticationcode/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qmessageauthenticationcode.pro. - ##################################################################### ## tst_qmessageauthenticationcode Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmessageauthenticationcode LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmessageauthenticationcode SOURCES tst_qmessageauthenticationcode.cpp diff --git a/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp b/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp index 08b7afae04..9e94ad77e9 100644 --- a/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp +++ b/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QCoreApplication> @@ -12,16 +12,64 @@ class tst_QMessageAuthenticationCode : public QObject { Q_OBJECT private slots: + void repeated_setKey_data(); + void repeated_setKey(); void result_data(); void result(); void result_incremental_data(); void result_incremental(); void addData_overloads_data(); void addData_overloads(); + void move(); + void swap(); }; Q_DECLARE_METATYPE(QCryptographicHash::Algorithm) +void tst_QMessageAuthenticationCode::repeated_setKey_data() +{ + using A = QCryptographicHash::Algorithm; + QTest::addColumn<A>("algo"); + + const auto me = QMetaEnum::fromType<A>(); + for (int i = 0, value; (value = me.value(i)) != -1; ++i) + QTest::addRow("%s", me.key(i)) << A(value); +} + +void tst_QMessageAuthenticationCode::repeated_setKey() +{ + QFETCH(const QCryptographicHash::Algorithm, algo); + + if (!QCryptographicHash::supportsAlgorithm(algo)) + QSKIP("QCryptographicHash doesn't support this algorithm"); + + // GIVEN: two long keys, so we're sure the key needs to be hashed in order + // to fit into the hash algorithm's block + + static const QByteArray key1(1024, 'a'); + static const QByteArray key2(2048, 'b'); + + // WHEN: processing the same message + + QMessageAuthenticationCode macX(algo); + QMessageAuthenticationCode mac1(algo, key1); + QMessageAuthenticationCode mac2(algo, key2); + + const auto check = [](QMessageAuthenticationCode &mac) { + mac.addData("This is nonsense, ignore it, please."); + return mac.result(); + }; + + macX.setKey(key1); + QCOMPARE(check(macX), check(mac1)); + + // THEN: the result does not depend on whether a new QMAC instance was used + // or an old one re-used (iow: setKey() reset()s) + + macX.setKey(key2); + QCOMPARE(check(macX), check(mac2)); +} + void tst_QMessageAuthenticationCode::result_data() { QTest::addColumn<QCryptographicHash::Algorithm>("algo"); @@ -99,14 +147,13 @@ void tst_QMessageAuthenticationCode::result() QFETCH(QByteArray, message); QFETCH(QByteArray, code); - QMessageAuthenticationCode mac(algo); - mac.setKey(key); + QMessageAuthenticationCode mac(algo, key); mac.addData(message); - QByteArray result = mac.result(); + QByteArrayView resultView = mac.resultView(); - QCOMPARE(result, code); + QCOMPARE(resultView, code); - result = QMessageAuthenticationCode::hash(message, key, algo); + const auto result = QMessageAuthenticationCode::hash(message, key, algo); QCOMPARE(result, code); } @@ -122,17 +169,16 @@ void tst_QMessageAuthenticationCode::result_incremental() QFETCH(QByteArray, message); QFETCH(QByteArray, code); - int index = message.length() / 2; + int index = message.size() / 2; QByteArray leftPart(message.mid(0, index)); QByteArray rightPart(message.mid(index)); QCOMPARE(leftPart + rightPart, message); - QMessageAuthenticationCode mac(algo); - mac.setKey(key); + QMessageAuthenticationCode mac(algo, key); mac.addData(leftPart); mac.addData(rightPart); - QByteArray result = mac.result(); + QByteArrayView result = mac.resultView(); QCOMPARE(result, code); } @@ -154,7 +200,7 @@ void tst_QMessageAuthenticationCode::addData_overloads() QMessageAuthenticationCode mac(algo); mac.setKey(key); mac.addData(message.constData(), message.size()); - QByteArray result = mac.result(); + QByteArrayView result = mac.resultView(); QCOMPARE(result, code); } @@ -166,12 +212,55 @@ void tst_QMessageAuthenticationCode::addData_overloads() QMessageAuthenticationCode mac(algo); mac.setKey(key); QVERIFY(mac.addData(&buffer)); - QByteArray result = mac.result(); + QByteArrayView result = mac.resultView(); buffer.close(); QCOMPARE(result, code); } } +void tst_QMessageAuthenticationCode::move() +{ + const QByteArray key = "123"; + + QMessageAuthenticationCode src(QCryptographicHash::Sha1, key); + src.addData("a"); + + // move constructor + auto intermediary = std::move(src); + intermediary.addData("b"); + + // move assign operator + QMessageAuthenticationCode dst(QCryptographicHash::Sha256, key); + dst.addData("no effect on the end result"); + dst = std::move(intermediary); + dst.addData("c"); + + QCOMPARE(dst.resultView(), + QMessageAuthenticationCode::hash("abc", key, QCryptographicHash::Sha1)); +} + +void tst_QMessageAuthenticationCode::swap() +{ + const QByteArray key1 = "123"; + const QByteArray key2 = "abcdefg"; + + QMessageAuthenticationCode mac1(QCryptographicHash::Sha1, key1); + QMessageAuthenticationCode mac2(QCryptographicHash::Sha256, key2); + + mac1.addData("da"); + mac2.addData("te"); + + mac1.swap(mac2); + + mac2.addData("ta"); + mac1.addData("st"); + + QCOMPARE(mac2.resultView(), + QMessageAuthenticationCode::hash("data", key1, QCryptographicHash::Sha1)); + QCOMPARE(mac1.resultView(), + QMessageAuthenticationCode::hash("test", key2, QCryptographicHash::Sha256)); +} + QTEST_MAIN(tst_QMessageAuthenticationCode) #include "tst_qmessageauthenticationcode.moc" diff --git a/tests/auto/corelib/tools/qoffsetstringarray/CMakeLists.txt b/tests/auto/corelib/tools/qoffsetstringarray/CMakeLists.txt index b613b55436..d0205cfa15 100644 --- a/tests/auto/corelib/tools/qoffsetstringarray/CMakeLists.txt +++ b/tests/auto/corelib/tools/qoffsetstringarray/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qoffsetstringarray.pro. - ##################################################################### ## tst_qoffsetstringarray Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qoffsetstringarray LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qoffsetstringarray SOURCES tst_qoffsetstringarray.cpp diff --git a/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp b/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp index 16c687bf89..dbb24e7af4 100644 --- a/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp +++ b/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -13,6 +13,7 @@ class tst_QOffsetStringArray : public QObject private slots: void init(); void access(); + void contains(); }; @@ -89,6 +90,16 @@ void tst_QOffsetStringArray::access() QCOMPARE(messages[6], ""); } +void tst_QOffsetStringArray::contains() +{ + QVERIFY(!messages.contains("")); + QVERIFY( messages.contains("level - 0")); + std::string l2 = "level - 2"; // make sure we don't compare pointer values + QVERIFY( messages.contains(l2)); + QByteArray L4 = "Level - 4"; + QVERIFY( messages.contains(L4, Qt::CaseInsensitive)); + QVERIFY(!messages.contains(L4, Qt::CaseSensitive)); +} QTEST_APPLESS_MAIN(tst_QOffsetStringArray) #include "tst_qoffsetstringarray.moc" diff --git a/tests/auto/corelib/tools/qpair/CMakeLists.txt b/tests/auto/corelib/tools/qpair/CMakeLists.txt index 3843fb1469..2dd048e015 100644 --- a/tests/auto/corelib/tools/qpair/CMakeLists.txt +++ b/tests/auto/corelib/tools/qpair/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qpair.pro. - ##################################################################### ## tst_qpair Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpair LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qpair SOURCES tst_qpair.cpp diff --git a/tests/auto/corelib/tools/qpair/tst_qpair.cpp b/tests/auto/corelib/tools/qpair/tst_qpair.cpp index dc20c793ea..0c9d87bb01 100644 --- a/tests/auto/corelib/tools/qpair/tst_qpair.cpp +++ b/tests/auto/corelib/tools/qpair/tst_qpair.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -65,7 +65,7 @@ static_assert( QTypeInfo<QPairPM>::isRelocatable ); static_assert(!QTypeInfo<QPairPP>::isComplex); static_assert( QTypeInfo<QPairPP>::isRelocatable ); -static_assert(!QTypeInfo<QPairPP>::isPointer); +static_assert(!std::is_pointer_v<QPairPP>); void tst_QPair::pairOfReferences() diff --git a/tests/auto/corelib/tools/qpoint/CMakeLists.txt b/tests/auto/corelib/tools/qpoint/CMakeLists.txt index e68ff17a77..f1402d8815 100644 --- a/tests/auto/corelib/tools/qpoint/CMakeLists.txt +++ b/tests/auto/corelib/tools/qpoint/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qpoint.pro. - ##################################################################### ## tst_qpoint Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpoint LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qpoint SOURCES tst_qpoint.cpp diff --git a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp index c183f79fb8..7fea787131 100644 --- a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp +++ b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp @@ -1,5 +1,27 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QPoint> +#ifdef QVARIANT_H +# error "This test requires qpoint.h to not include qvariant.h" +#endif + +// don't assume <type_traits> +template <typename T, typename U> +constexpr inline bool my_is_same_v = false; +template <typename T> +constexpr inline bool my_is_same_v<T, T> = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v<decltype(get<0>(std::declval<QPoint cvref >())), int cvref >); \ + static_assert(my_is_same_v<decltype(get<1>(std::declval<QPoint cvref >())), int cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK #include <QTest> #include <QBuffer> diff --git a/tests/auto/corelib/tools/qpointf/CMakeLists.txt b/tests/auto/corelib/tools/qpointf/CMakeLists.txt index b05a74d650..16e5a9036a 100644 --- a/tests/auto/corelib/tools/qpointf/CMakeLists.txt +++ b/tests/auto/corelib/tools/qpointf/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qpointf.pro. - ##################################################################### ## tst_qpointf Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpointf LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qpointf SOURCES tst_qpointf.cpp diff --git a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp index a6bd0a9779..392c22c70a 100644 --- a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp +++ b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp @@ -1,5 +1,27 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QPointF> +#ifdef QVARIANT_H +# error "This test requires qpoint.h to not include qvariant.h" +#endif + +// don't assume <type_traits> +template <typename T, typename U> +constexpr inline bool my_is_same_v = false; +template <typename T> +constexpr inline bool my_is_same_v<T, T> = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v<decltype(get<0>(std::declval<QPointF cvref >())), qreal cvref >); \ + static_assert(my_is_same_v<decltype(get<1>(std::declval<QPointF cvref >())), qreal cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK #include <QTest> #include <QBuffer> diff --git a/tests/auto/corelib/tools/qqueue/CMakeLists.txt b/tests/auto/corelib/tools/qqueue/CMakeLists.txt index c559c66f24..bf229eee6a 100644 --- a/tests/auto/corelib/tools/qqueue/CMakeLists.txt +++ b/tests/auto/corelib/tools/qqueue/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qqueue.pro. - ##################################################################### ## tst_qqueue Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qqueue LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qqueue SOURCES tst_qqueue.cpp diff --git a/tests/auto/corelib/tools/qqueue/tst_qqueue.cpp b/tests/auto/corelib/tools/qqueue/tst_qqueue.cpp index ed66806f96..44d4c34768 100644 --- a/tests/auto/corelib/tools/qqueue/tst_qqueue.cpp +++ b/tests/auto/corelib/tools/qqueue/tst_qqueue.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/tools/qrect/CMakeLists.txt b/tests/auto/corelib/tools/qrect/CMakeLists.txt index 317295c8f9..a02e1c33a5 100644 --- a/tests/auto/corelib/tools/qrect/CMakeLists.txt +++ b/tests/auto/corelib/tools/qrect/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qrect.pro. - ##################################################################### ## tst_qrect Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qrect LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qrect SOURCES tst_qrect.cpp diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp index 65cd68108a..0f3dd1a0ef 100644 --- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp +++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <qrect.h> @@ -4315,8 +4315,6 @@ void tst_QRect::containsPointF_data() QTest::addColumn<QPointF>("point"); QTest::addColumn<bool>("contains"); - QTest::newRow("test 27") << QRectF() << QPointF() << false; - QTest::newRow("test 01") << QRectF(0, 0, 10, 10) << QPointF( 0, 0) << true; QTest::newRow("test 02") << QRectF(0, 0, 10, 10) << QPointF( 0, 10) << true; QTest::newRow("test 03") << QRectF(0, 0, 10, 10) << QPointF(10, 0) << true; diff --git a/tests/auto/corelib/tools/qringbuffer/CMakeLists.txt b/tests/auto/corelib/tools/qringbuffer/CMakeLists.txt index 60d1cea9fa..cfb7c6f461 100644 --- a/tests/auto/corelib/tools/qringbuffer/CMakeLists.txt +++ b/tests/auto/corelib/tools/qringbuffer/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qringbuffer.pro. - ##################################################################### ## tst_qringbuffer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qringbuffer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qringbuffer SOURCES tst_qringbuffer.cpp diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp index dec6319159..c7b79cfae1 100644 --- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp +++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QBuffer> diff --git a/tests/auto/corelib/tools/qscopedpointer/CMakeLists.txt b/tests/auto/corelib/tools/qscopedpointer/CMakeLists.txt index 33c7140ced..7bfcfdebbf 100644 --- a/tests/auto/corelib/tools/qscopedpointer/CMakeLists.txt +++ b/tests/auto/corelib/tools/qscopedpointer/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qscopedpointer.pro. - ##################################################################### ## tst_qscopedpointer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscopedpointer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qscopedpointer SOURCES tst_qscopedpointer.cpp diff --git a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp index 367cfb5b5d..3468c97f42 100644 --- a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp +++ b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/QScopedPointer> diff --git a/tests/auto/corelib/tools/qscopedvaluerollback/CMakeLists.txt b/tests/auto/corelib/tools/qscopedvaluerollback/CMakeLists.txt index fc945c1c0e..359a910a0a 100644 --- a/tests/auto/corelib/tools/qscopedvaluerollback/CMakeLists.txt +++ b/tests/auto/corelib/tools/qscopedvaluerollback/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qscopedvaluerollback.pro. - ##################################################################### ## tst_qscopedvaluerollback Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscopedvaluerollback LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qscopedvaluerollback SOURCES tst_qscopedvaluerollback.cpp diff --git a/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp b/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp index ad36504ff6..3b493b4e75 100644 --- a/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp +++ b/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/QScopedValueRollback> diff --git a/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt b/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt index 05fb843afd..6f6d664554 100644 --- a/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt +++ b/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qscopeguard.pro. - ##################################################################### ## tst_qscopeguard Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscopeguard LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qscopeguard SOURCES tst_qscopeguard.cpp diff --git a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp index 015cbcc0e7..b7c2b952e2 100644 --- a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp +++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp @@ -1,10 +1,12 @@ // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com> // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/QScopeGuard> +#include <optional> + /*! \class tst_QScopeGuard \internal @@ -20,6 +22,7 @@ private Q_SLOTS: void construction(); void constructionFromLvalue(); void constructionFromRvalue(); + void optionalGuard(); void leavingScope(); void exceptions(); }; @@ -117,6 +120,24 @@ void tst_QScopeGuard::constructionFromRvalue() QCOMPARE(Callable::moved, 1); } +void tst_QScopeGuard::optionalGuard() +{ + int i = 0; + auto lambda = [&] { ++i; }; + std::optional sg = false ? std::optional{qScopeGuard(lambda)} : std::nullopt; + QVERIFY(!sg); + QCOMPARE(i, 0); + sg.emplace(qScopeGuard(lambda)); + QVERIFY(sg); + sg->dismiss(); + sg.reset(); + QCOMPARE(i, 0); + sg.emplace(qScopeGuard(lambda)); + QCOMPARE(i, 0); + sg.reset(); + QCOMPARE(i, 1); +} + void tst_QScopeGuard::leavingScope() { auto cleanup = qScopeGuard([] { s_globalState++; QCOMPARE(s_globalState, 3); }); diff --git a/tests/auto/corelib/tools/qset/CMakeLists.txt b/tests/auto/corelib/tools/qset/CMakeLists.txt index 17e80d4357..9e3e33ee7c 100644 --- a/tests/auto/corelib/tools/qset/CMakeLists.txt +++ b/tests/auto/corelib/tools/qset/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qset.pro. - ##################################################################### ## tst_qset Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qset LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qset SOURCES tst_qset.cpp diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp index bd88c19bd0..116d38112b 100644 --- a/tests/auto/corelib/tools/qset/tst_qset.cpp +++ b/tests/auto/corelib/tools/qset/tst_qset.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <qset.h> @@ -8,7 +8,7 @@ int toNumber(const QString &str) { int res = 0; - for (int i = 0; i < str.length(); ++i) + for (int i = 0; i < str.size(); ++i) res = (res * 10) + str[i].digitValue(); return res; } @@ -139,44 +139,44 @@ void tst_QSet::size() QSet<int> set; QVERIFY(set.size() == 0); QVERIFY(set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); QVERIFY(!set.isDetached()); set.insert(1); QVERIFY(set.size() == 1); QVERIFY(!set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); set.insert(1); QVERIFY(set.size() == 1); QVERIFY(!set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); set.insert(2); QVERIFY(set.size() == 2); QVERIFY(!set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); set.remove(1); QVERIFY(set.size() == 1); QVERIFY(!set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); set.remove(1); QVERIFY(set.size() == 1); QVERIFY(!set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); set.remove(2); QVERIFY(set.size() == 0); QVERIFY(set.isEmpty()); - QVERIFY(set.count() == set.size()); + QVERIFY(set.size() == set.size()); QVERIFY(set.isEmpty() == set.empty()); } @@ -232,27 +232,39 @@ void tst_QSet::squeeze() set.squeeze(); QVERIFY(set.capacity() < 100); - for (int i = 0; i < 512; ++i) + for (int i = 0; i < 500; ++i) set.insert(i); - QVERIFY(set.capacity() == 512); + QCOMPARE(set.size(), 500); + + // squeezed capacity for 500 elements + qsizetype capacity = set.capacity(); // current implementation: 512 + QCOMPARE_GE(capacity, set.size()); set.reserve(50000); - QVERIFY(set.capacity() >= 50000); + QVERIFY(set.capacity() >= 50000); // current implementation: 65536 set.squeeze(); - QVERIFY(set.capacity() == 512); + QCOMPARE(set.capacity(), capacity); + // removing elements does not shed capacity set.remove(499); - QVERIFY(set.capacity() == 512); + QCOMPARE(set.capacity(), capacity); set.insert(499); - QVERIFY(set.capacity() == 512); + QCOMPARE(set.capacity(), capacity); - set.insert(1000); - QVERIFY(set.capacity() == 1024); + // grow it beyond the current capacity + for (int i = set.size(); i <= capacity; ++i) + set.insert(i); + QCOMPARE(set.size(), capacity + 1); + QCOMPARE_GT(set.capacity(), capacity + 1);// current implementation: 2 * capacity (1024) for (int i = 0; i < 500; ++i) set.remove(i); + + // removing elements does not shed capacity + QCOMPARE_GT(set.capacity(), capacity + 1); + set.squeeze(); QVERIFY(set.capacity() < 100); } @@ -844,7 +856,7 @@ void tst_QSet::setOperationsOnEmptySet() empty.unite(nonEmpty); QCOMPARE(empty, nonEmpty); - QVERIFY(empty.isDetached()); + QVERIFY(!empty.isDetached()); } } @@ -927,13 +939,11 @@ void tst_QSet::javaIterator() QSetIterator<QString> i(set1); QSetIterator<QString> j(set1); - int n = 0; while (i.hasNext()) { QVERIFY(j.hasNext()); set1.remove(i.peekNext()); sum1 += toNumber(i.next()); sum2 += toNumber(j.next()); - ++n; } QVERIFY(!j.hasNext()); QVERIFY(sum1 == 24999 * 25000 / 2); @@ -1011,7 +1021,7 @@ void tst_QSet::makeSureTheComfortFunctionsCompile() void tst_QSet::initializerList() { QSet<int> set = {1, 1, 2, 3, 4, 5}; - QCOMPARE(set.count(), 5); + QCOMPARE(set.size(), 5); QVERIFY(set.contains(1)); QVERIFY(set.contains(2)); QVERIFY(set.contains(3)); @@ -1020,7 +1030,7 @@ void tst_QSet::initializerList() // check _which_ of the equal elements gets inserted (in the QHash/QMap case, it's the last): const QSet<IdentityTracker> set2 = {{1, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; - QCOMPARE(set2.count(), 5); + QCOMPARE(set2.size(), 5); const int dummy = -1; const IdentityTracker searchKey = {1, dummy}; QCOMPARE(set2.find(searchKey)->id, 0); @@ -1045,17 +1055,27 @@ void tst_QSet::qhash() s1.reserve(4); s1 << 400 << 300 << 200 << 100; - // also change the seed: - QHashSeed::resetRandomGlobalSeed(); + int retries = 128; + while (--retries >= 0) { + // reset the global seed to something different + QHashSeed::resetRandomGlobalSeed(); - QSet<int> s2; - s2.reserve(100); // provoke different bucket counts - s2 << 100 << 200 << 300 << 400; // and insert elements in different order, too + QSet<int> s2; + s2.reserve(100); // provoke different bucket counts + s2 << 100 << 200 << 300 << 400; // and insert elements in different order, too + QVERIFY(s1.capacity() != s2.capacity()); - QVERIFY(s1.capacity() != s2.capacity()); - QCOMPARE(s1, s2); - QVERIFY(!std::equal(s1.cbegin(), s1.cend(), s2.cbegin())); // verify that the order _is_ different - QCOMPARE(qHash(s1), qHash(s2)); + // see if we got a _different_ order + if (std::equal(s1.cbegin(), s1.cend(), s2.cbegin())) + continue; + + // check if the two QHashes still compare equal and produce the + // same hash, despite containing elements in different orders + QCOMPARE(s1, s2); + QCOMPARE(qHash(s1), qHash(s2)); + } + QVERIFY2(retries != 0, "Could not find a QSet with a different order of elements even " + "after a lot of retries. This is unlikely, but possible."); } // diff --git a/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt b/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt index 518512560c..0db0cba4c0 100644 --- a/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt +++ b/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt @@ -5,6 +5,12 @@ ## tst_qsharedpointer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsharedpointer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsharedpointer SOURCES forwarddeclared.cpp diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp index b97c84da85..c676924668 100644 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "externaltests.h" @@ -55,7 +55,7 @@ namespace QTest { { if (process.state() == QProcess::Running) { process.terminate(); - QThread::msleep(20); + QThread::sleep(std::chrono::milliseconds{20}); if (process.state() == QProcess::Running) process.kill(); } diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.h b/tests/auto/corelib/tools/qsharedpointer/externaltests.h index 0d290ef3c7..790ca61992 100644 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.h +++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QTEST_EXTERNAL_TESTS_H diff --git a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp index d8a5b3125b..5a0af60c11 100644 --- a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "forwarddeclared.h" #include "qsharedpointer.h" diff --git a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h index 90811a9074..ba436d99cf 100644 --- a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h +++ b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h @@ -1,6 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef FORWARDDECLARED_H #define FORWARDDECLARED_H diff --git a/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp b/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp index 7d31897db7..b572fa1b9f 100644 --- a/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only /* * This file exists because tst_qsharedpointer.cpp is compiled with diff --git a/tests/auto/corelib/tools/qsharedpointer/nontracked.h b/tests/auto/corelib/tools/qsharedpointer/nontracked.h index 7562de43e6..e10ea08a4d 100644 --- a/tests/auto/corelib/tools/qsharedpointer/nontracked.h +++ b/tests/auto/corelib/tools/qsharedpointer/nontracked.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef NONTRACKED_H #define NONTRACKED_H diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 90609eb998..f42637a3fe 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2021 The Qt Company Ltd. // Copyright (C) 2022 Intel Corporation. // Copyright (C) 2021 Klarälvdalens Datakonsult AB. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #define QT_SHAREDPOINTER_TRACK_POINTERS #include "qsharedpointer.h" @@ -91,6 +91,7 @@ private slots: void invalidConstructs_data(); void invalidConstructs(); #endif + void ownerComparisons(); // let invalidConstructs be the last test, because it's the slowest; // add new tests above this block @@ -1275,6 +1276,22 @@ void tst_QSharedPointer::virtualBaseDifferentPointers() QVERIFY(baseptr == aBase); } safetyCheck(); + { + VirtualDerived *aData = new VirtualDerived; + + QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>(aData); + QWeakPointer<VirtualDerived> wptr = ptr; + + ptr.reset(); + QVERIFY(wptr.toStrongRef().isNull()); + + QWeakPointer<Data> wptr2 = wptr; + QVERIFY(wptr2.toStrongRef().isNull()); + + QWeakPointer<Data> wptr3 = std::move(wptr); + QVERIFY(wptr3.toStrongRef().isNull()); + } + safetyCheck(); } #ifndef QTEST_NO_RTTI @@ -1982,7 +1999,7 @@ class StrongThread: public QThread protected: void run() override { - usleep(QRandomGenerator::global()->bounded(2000)); + sleep(std::chrono::microseconds{QRandomGenerator::global()->bounded(2000)}); ptr->ref(); ptr.clear(); } @@ -1995,7 +2012,7 @@ class WeakThread: public QThread protected: void run() override { - usleep(QRandomGenerator::global()->bounded(2000)); + sleep(std::chrono::microseconds{QRandomGenerator::global()->bounded(2000)}); QSharedPointer<ThreadData> ptr = weak; if (ptr) ptr->ref(); @@ -2058,11 +2075,11 @@ void tst_QSharedPointer::threadStressTest() base.clear(); // start threads - for (int i = 0; i < allThreads.count(); ++i) + for (int i = 0; i < allThreads.size(); ++i) if (allThreads[i]) allThreads[i]->start(); // wait for them to finish - for (int i = 0; i < allThreads.count(); ++i) + for (int i = 0; i < allThreads.size(); ++i) if (allThreads[i]) allThreads[i]->wait(); qDeleteAll(allThreads); @@ -2825,5 +2842,140 @@ void tst_QSharedPointer::overloads() weakOverloaded.test(); } +void tst_QSharedPointer::ownerComparisons() +{ + using SP = QSharedPointer<int>; + using WP = QWeakPointer<int>; + +#define CHECK_EQ(a, b) \ + do { \ + QVERIFY(a.owner_equal(b)); \ + QVERIFY(b.owner_equal(a)); \ + QVERIFY(!a.owner_before(b)); \ + QVERIFY(!b.owner_before(a)); \ + QVERIFY(a.owner_hash() == b.owner_hash()); \ + } while (false) + +#define CHECK_NOT_EQ(a, b) \ + do { \ + QVERIFY(!a.owner_equal(b)); \ + QVERIFY(!b.owner_equal(a)); \ + QVERIFY(a.owner_before(b) || b.owner_before(a)); \ + } while (false) + + // null + { + SP sp1; + SP sp2; + WP wp1 = sp1; + WP wp2; + + CHECK_EQ(sp1, sp1); + CHECK_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp1, wp2); + CHECK_EQ(wp2, wp2); + } + + // same owner + { + SP sp1 = SP::create(123); + SP sp2 = sp1; + WP wp1 = sp1; + SP wp2 = sp2; + + CHECK_EQ(sp1, sp1); + CHECK_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp1, wp2); + } + + // owning vs null + { + SP sp1 = SP::create(123); + SP sp2; + WP wp1 = sp1; + WP wp2 = sp2; + + CHECK_EQ(sp1, sp1); + CHECK_NOT_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + // different owners + { + SP sp1 = SP::create(123); + SP sp2 = SP::create(456); + WP wp1 = sp1; + WP wp2 = sp2; + + CHECK_EQ(sp1, sp1); + CHECK_NOT_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + // reset vs. null + { + SP sp1 = SP::create(123); + SP sp2; + WP wp1 = sp1; + WP wp2; + + CHECK_EQ(sp1, sp1); + CHECK_NOT_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_NOT_EQ(sp1, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + + sp1.reset(); + + CHECK_EQ(sp1, sp1); + CHECK_EQ(sp1, sp2); + CHECK_NOT_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + // expired weak pointers + { + WP wp1 = SP::create(123); + WP wp2; + + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + { + WP wp1 = SP::create(123); + WP wp2 = wp1; + + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp1, wp2); + } + + { + WP wp1 = SP::create(123); + WP wp2 = SP::create(456); + + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp2, wp2); + CHECK_NOT_EQ(wp1, wp2); + } +#undef CHECK_EQ +#undef CHECK_NOT_EQ +} + QTEST_MAIN(tst_QSharedPointer) #include "tst_qsharedpointer.moc" diff --git a/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp b/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp index 07c837304e..b39eee7d98 100644 --- a/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifdef QT_SHAREDPOINTER_TRACK_POINTERS # undef QT_SHAREDPOINTER_TRACK_POINTERS diff --git a/tests/auto/corelib/tools/qsharedpointer/wrapper.h b/tests/auto/corelib/tools/qsharedpointer/wrapper.h index 32cc09f422..3b0bc09fed 100644 --- a/tests/auto/corelib/tools/qsharedpointer/wrapper.h +++ b/tests/auto/corelib/tools/qsharedpointer/wrapper.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef WRAPPER_H #define WRAPPER_H diff --git a/tests/auto/corelib/tools/qsize/CMakeLists.txt b/tests/auto/corelib/tools/qsize/CMakeLists.txt index 766b1bb3dc..91de696ddd 100644 --- a/tests/auto/corelib/tools/qsize/CMakeLists.txt +++ b/tests/auto/corelib/tools/qsize/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qsize.pro. - ##################################################################### ## tst_qsize Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsize LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsize SOURCES tst_qsize.cpp diff --git a/tests/auto/corelib/tools/qsize/tst_qsize.cpp b/tests/auto/corelib/tools/qsize/tst_qsize.cpp index 54ffd9fcfd..c9699c5e76 100644 --- a/tests/auto/corelib/tools/qsize/tst_qsize.cpp +++ b/tests/auto/corelib/tools/qsize/tst_qsize.cpp @@ -1,5 +1,27 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QSize> +#ifdef QVARIANT_H +# error "This test requires qsize.h to not include qvariant.h" +#endif + +// don't assume <type_traits> +template <typename T, typename U> +constexpr inline bool my_is_same_v = false; +template <typename T> +constexpr inline bool my_is_same_v<T, T> = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v<decltype(get<0>(std::declval<QSize cvref >())), int cvref >); \ + static_assert(my_is_same_v<decltype(get<1>(std::declval<QSize cvref >())), int cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK #include <QTest> #include <qsize.h> diff --git a/tests/auto/corelib/tools/qsizef/CMakeLists.txt b/tests/auto/corelib/tools/qsizef/CMakeLists.txt index fe68c4c15f..9adaafe2ea 100644 --- a/tests/auto/corelib/tools/qsizef/CMakeLists.txt +++ b/tests/auto/corelib/tools/qsizef/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qsizef.pro. - ##################################################################### ## tst_qsizef Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsizef LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsizef SOURCES tst_qsizef.cpp diff --git a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp index 0a53de68c9..ee33fa13b6 100644 --- a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp +++ b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp @@ -1,5 +1,27 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QSizeF> +#ifdef QVARIANT_H +# error "This test requires qsize.h to not include qvariant.h" +#endif + +// don't assume <type_traits> +template <typename T, typename U> +constexpr inline bool my_is_same_v = false; +template <typename T> +constexpr inline bool my_is_same_v<T, T> = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v<decltype(get<0>(std::declval<QSizeF cvref >())), qreal cvref >); \ + static_assert(my_is_same_v<decltype(get<1>(std::declval<QSizeF cvref >())), qreal cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK #include <QTest> #include <qsize.h> diff --git a/tests/auto/corelib/tools/qspan/CMakeLists.txt b/tests/auto/corelib/tools/qspan/CMakeLists.txt new file mode 100644 index 0000000000..595d19dc43 --- /dev/null +++ b/tests/auto/corelib/tools/qspan/CMakeLists.txt @@ -0,0 +1,13 @@ +# 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_qspan LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qspan + SOURCES + tst_qspan.cpp +) diff --git a/tests/auto/corelib/tools/qspan/tst_qspan.cpp b/tests/auto/corelib/tools/qspan/tst_qspan.cpp new file mode 100644 index 0000000000..91d2ecf739 --- /dev/null +++ b/tests/auto/corelib/tools/qspan/tst_qspan.cpp @@ -0,0 +1,450 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QSpan> + +#include <QList> +#include <QTest> + +#include <algorithm> +#include <array> +#ifdef __cpp_lib_span +#include <span> +#endif +#include <vector> + +namespace { + +struct NotNothrowMovable { + NotNothrowMovable(NotNothrowMovable &&) noexcept(false) {}; + NotNothrowMovable &operator=(NotNothrowMovable &&) noexcept(false) { return *this; }; +}; +static_assert(!std::is_nothrow_move_constructible_v<NotNothrowMovable>); +static_assert(!std::is_nothrow_move_assignable_v<NotNothrowMovable>); + +} // unnamed namespace + +// +// QSpan is nothrow movable even if the payload type is not: +// +static_assert(std::is_nothrow_move_constructible_v<QSpan<NotNothrowMovable>>); +static_assert(std::is_nothrow_move_constructible_v<QSpan<NotNothrowMovable, 42>>); +static_assert(std::is_nothrow_move_constructible_v<QSpan<NotNothrowMovable, 0>>); + +static_assert(std::is_nothrow_move_assignable_v<QSpan<NotNothrowMovable>>); +static_assert(std::is_nothrow_move_assignable_v<QSpan<NotNothrowMovable, 42>>); +static_assert(std::is_nothrow_move_assignable_v<QSpan<NotNothrowMovable, 0>>); + +// +// All QSpans are trivially destructible and trivially copyable: +// +static_assert(std::is_trivially_copyable_v<QSpan<NotNothrowMovable>>); +static_assert(std::is_trivially_copyable_v<QSpan<NotNothrowMovable, 42>>); +static_assert(std::is_trivially_copyable_v<QSpan<NotNothrowMovable, 0>>); + +static_assert(std::is_trivially_destructible_v<QSpan<NotNothrowMovable>>); +static_assert(std::is_trivially_destructible_v<QSpan<NotNothrowMovable, 42>>); +static_assert(std::is_trivially_destructible_v<QSpan<NotNothrowMovable, 0>>); + +// +// Fixed-size QSpans implicitly convert to variable-sized ones: +// +static_assert(std::is_convertible_v<QSpan<int, 42>, QSpan<int>>); +static_assert(std::is_convertible_v<QSpan<int, 0>, QSpan<int>>); + +#ifdef __cpp_lib_span +static_assert(std::is_convertible_v<std::span<int, 42>, QSpan<int>>); +static_assert(std::is_convertible_v<std::span<int, 0>, QSpan<int>>); + +#ifdef __cpp_lib_concepts +// requires enable_borrowed_range +static_assert(std::is_convertible_v<QSpan<int, 42>, std::span<int>>); +static_assert(std::is_convertible_v<QSpan<int, 0>, std::span<int>>); +#endif // __cpp_lib_concepts +#endif // __cpp_lib_span + +// +// Mutable spans implicitly convert to read-only ones, but not vice versa: +// +static_assert(std::is_convertible_v<QSpan<int>, QSpan<const int>>); +static_assert(std::is_convertible_v<QSpan<int, 42>, QSpan<const int, 42>>); +static_assert(std::is_convertible_v<QSpan<int, 0>, QSpan<const int, 0>>); + +static_assert(!std::is_convertible_v<QSpan<const int>, QSpan<int>>); +static_assert(!std::is_convertible_v<QSpan<const int, 42>, QSpan<int, 42>>); +static_assert(!std::is_convertible_v<QSpan<const int, 0>, QSpan<int, 0>>); + +#ifdef __cpp_lib_span +static_assert(std::is_convertible_v<std::span<int>, QSpan<const int>>); +static_assert(std::is_convertible_v<std::span<int, 42>, QSpan<const int, 42>>); +static_assert(std::is_convertible_v<std::span<int, 0>, QSpan<const int, 0>>); + +static_assert(!std::is_convertible_v<std::span<const int>, QSpan<int>>); +static_assert(!std::is_convertible_v<std::span<const int, 42>, QSpan<int, 42>>); +static_assert(!std::is_convertible_v<std::span<const int, 0>, QSpan<int, 0>>); + +static_assert(std::is_convertible_v<QSpan<int>, std::span<const int>>); +// fixed-size std::span constructors are explicit: +static_assert(!std::is_convertible_v<QSpan<int, 42>, std::span<const int, 42>>); +static_assert(!std::is_convertible_v<QSpan<int, 0>, std::span<const int, 0>>); +// observe: is_convertible<From,To>, but is_constuctible<To,From>! +static_assert(std::is_constructible_v<std::span<const int, 42>, QSpan<int, 42>>); +static_assert(std::is_constructible_v<std::span<const int, 0>, QSpan<int, 0>>); + +static_assert(!std::is_convertible_v<QSpan<const int>, std::span<int>>); +static_assert(!std::is_convertible_v<QSpan<const int, 42>, std::span<int, 42>>); +static_assert(!std::is_convertible_v<QSpan<const int, 0>, std::span<int, 0>>); +#endif // __cpp_lib_span + +// Spans don't convert from nonsense: +static_assert(!std::is_constructible_v<QSpan<const int>, int&&>); + +// Span is constructible from initializer_list +static_assert( std::is_convertible_v<std::initializer_list<int>, QSpan<const int>>); +static_assert(!std::is_convertible_v<std::initializer_list<int>, QSpan< int>>); +static_assert(!std::is_constructible_v<QSpan<int>, std::initializer_list<int>>); + +static_assert( std::is_convertible_v<std::initializer_list<int>, QSpan<const int, 4>>); // non-standard, but QSpan considers initializer_list a range +static_assert( std::is_constructible_v<QSpan<const int, 4>, std::initializer_list<int>>); +static_assert(!std::is_constructible_v<QSpan< int, 4>, std::initializer_list<int>>); + +class tst_QSpan : public QObject +{ + Q_OBJECT +public: + using QObject::QObject; + +private Q_SLOTS: + void onlyZeroExtentSpansHaveDefaultCtors() const; + void zeroExtentSpansMaintainADataPointer() const; + void fromArray() const; + void fromStdArray() const; + void fromStdInitializerList() const; + void fromZeroSizeStdArray() const; + void fromStdVector() const; + void fromQList() const; + void fromInitList() const; + +private: + template <typename T, std::size_t N> + void check_nonempty_span(QSpan<T, N>, qsizetype expectedSize) const; + template <typename T, std::size_t N> + void check_empty_span_incl_subspans(QSpan<T, N>) const; + template <typename T, std::size_t N> + void check_empty_span(QSpan<T, N>) const; + template <typename T, std::size_t N> + void check_null_span(QSpan<T, N>) const; + + template <std::size_t ExpectedExtent, typename C> + void from_container_impl(C &&c) const; + template <typename C> + void from_variable_size_container_impl(C &&c) const; +}; + +#define RETURN_IF_FAILED() \ + do { if (QTest::currentTestFailed()) return; } while (false) + +void tst_QSpan::onlyZeroExtentSpansHaveDefaultCtors() const +{ + static_assert(std::is_nothrow_default_constructible_v<QSpan<int, 0>>); + static_assert(std::is_nothrow_default_constructible_v<QSpan<const int, 0>>); + static_assert(std::is_nothrow_default_constructible_v<QSpan<int>>); + static_assert(std::is_nothrow_default_constructible_v<QSpan<const int, 0>>); + + QSpan<int, 0> si; + check_null_span(si); + RETURN_IF_FAILED(); + + QSpan<const int, 0> sci; + check_null_span(sci); + RETURN_IF_FAILED(); + + QSpan<int> sdi; + check_null_span(sdi); + RETURN_IF_FAILED(); + + QSpan<const int> sdci; + check_null_span(sdci); + RETURN_IF_FAILED(); + + static_assert(!std::is_default_constructible_v<QSpan<int, 1>>); + static_assert(!std::is_default_constructible_v<QSpan<const int, 42>>); +} + +void tst_QSpan::zeroExtentSpansMaintainADataPointer() const +{ + int i; + QSpan<int, 0> si{&i, 0}; + QCOMPARE(si.data(), &i); + check_empty_span_incl_subspans(si); + RETURN_IF_FAILED(); + + QSpan<const int, 0> sci{&i, 0}; + QCOMPARE(sci.data(), &i); + check_empty_span_incl_subspans(sci); + RETURN_IF_FAILED(); + + QSpan<int, 0> sdi{&i, 0}; + QCOMPARE(sdi.data(), &i); + check_empty_span_incl_subspans(sdi); + RETURN_IF_FAILED(); + + QSpan<const int, 0> sdci{&i, 0}; + QCOMPARE(sdci.data(), &i); + check_empty_span_incl_subspans(sdci); + RETURN_IF_FAILED(); +} + +template <typename T, std::size_t N> +void tst_QSpan::check_nonempty_span(QSpan<T, N> s, qsizetype expectedSize) const +{ + static_assert(N > 0); + QCOMPARE_GT(expectedSize, 0); // otherwise, use check_empty_span! + + QVERIFY(!s.empty()); + QVERIFY(!s.isEmpty()); + + QCOMPARE_EQ(s.size(), expectedSize); + QCOMPARE_NE(s.data(), nullptr); + + QCOMPARE_NE(s.begin(), s.end()); + QCOMPARE_NE(s.rbegin(), s.rend()); + QCOMPARE_NE(s.cbegin(), s.cend()); + QCOMPARE_NE(s.crbegin(), s.crend()); + + QCOMPARE_EQ(s.end() - s.begin(), s.size()); + QCOMPARE_EQ(s.cend() - s.cbegin(), s.size()); + QCOMPARE_EQ(s.rend() - s.rbegin(), s.size()); + QCOMPARE_EQ(s.crend() - s.crbegin(), s.size()); + + QCOMPARE_EQ(std::addressof(s.front()), std::addressof(*s.begin())); + QCOMPARE_EQ(std::addressof(s.front()), std::addressof(*s.cbegin())); + QCOMPARE_EQ(std::addressof(s.front()), std::addressof(s[0])); + QCOMPARE_EQ(std::addressof(s.back()), std::addressof(*s.rbegin())); + QCOMPARE_EQ(std::addressof(s.back()), std::addressof(*s.crbegin())); + QCOMPARE_EQ(std::addressof(s.back()), std::addressof(s[s.size() - 1])); + + // ### more? + + if (expectedSize == 1) { + // don't run into Mandates: Offset >= Extent + if constexpr (N > 0) { // incl. N == std::dynamic_extent + check_empty_span_incl_subspans(s.template subspan<1>()); + RETURN_IF_FAILED(); + } + check_empty_span_incl_subspans(s.subspan(1)); + RETURN_IF_FAILED(); + } else { + // don't run into Mandates: Offset >= Extent + if constexpr (N > 1) { // incl. N == std::dynamic_extent + check_nonempty_span(s.template subspan<1>(), expectedSize - 1); + RETURN_IF_FAILED(); + } + check_nonempty_span(s.subspan(1), expectedSize - 1); + RETURN_IF_FAILED(); + } +} + +template <typename T, std::size_t N> +void tst_QSpan::check_empty_span(QSpan<T, N> s) const +{ + QVERIFY(s.empty()); + QVERIFY(s.isEmpty()); + + QCOMPARE_EQ(s.size(), 0); + + QCOMPARE_EQ(s.begin(), s.end()); + QCOMPARE_EQ(s.cbegin(), s.cend()); + QCOMPARE_EQ(s.rbegin(), s.rend()); + QCOMPARE_EQ(s.crbegin(), s.crend()); +} + +template <typename T, std::size_t N> +void tst_QSpan::check_empty_span_incl_subspans(QSpan<T, N> s) const +{ + check_empty_span(s); + RETURN_IF_FAILED(); + + { + const auto fi = s.template first<0>(); + check_empty_span(fi); + RETURN_IF_FAILED(); + QCOMPARE_EQ(fi.data(), s.data()); + } + { + const auto la = s.template last<0>(); + check_empty_span(la); + RETURN_IF_FAILED(); + QCOMPARE_EQ(la.data(), s.data()); + } + { + const auto ss = s.template subspan<0>(); + check_empty_span(ss); + RETURN_IF_FAILED(); + QCOMPARE_EQ(ss.data(), s.data()); + } + { + const auto ss = s.template subspan<0, 0>(); + check_empty_span(ss); + RETURN_IF_FAILED(); + QCOMPARE_EQ(ss.data(), s.data()); + } + + { + const auto fi = s.first(0); + check_empty_span(fi); + RETURN_IF_FAILED(); + QCOMPARE_EQ(fi.data(), s.data()); + } + { + const auto la = s.last(0); + check_empty_span(la); + RETURN_IF_FAILED(); + QCOMPARE_EQ(la.data(), s.data()); + } + { + const auto ss = s.subspan(0); + check_empty_span(ss); + RETURN_IF_FAILED(); + QCOMPARE_EQ(ss.data(), s.data()); + } + { + const auto ss = s.subspan(0, 0); + check_empty_span(ss); + RETURN_IF_FAILED(); + QCOMPARE_EQ(ss.data(), s.data()); + } +} + + +template<typename T, std::size_t N> +void tst_QSpan::check_null_span(QSpan<T, N> s) const +{ + QCOMPARE_EQ(s.data(), nullptr); + QCOMPARE_EQ(s.begin(), nullptr); + QCOMPARE_EQ(s.cbegin(), nullptr); + QCOMPARE_EQ(s.end(), nullptr); + check_empty_span_incl_subspans(s); +} + +template <std::size_t ExpectedExtent, typename C> +void tst_QSpan::from_container_impl(C &&c) const +{ + const auto c_size = qsizetype(QSpanPrivate::adl_size(c)); + const auto c_data = QSpanPrivate::adl_data(c); + + using V = std::remove_reference_t<QSpanPrivate::range_reference_t<C>>; + { + QSpan si = c; // CTAD + static_assert(std::is_same_v<decltype(si), QSpan<V, ExpectedExtent>>); + + QCOMPARE_EQ(si.size(), c_size); + QCOMPARE_EQ(si.data(), c_data); + + check_nonempty_span(si, c_size); + RETURN_IF_FAILED(); + + QSpan<const int> sci = c; + + QCOMPARE_EQ(sci.size(), c_size); + QCOMPARE_EQ(sci.data(), c_data); + + check_nonempty_span(sci, c_size); + RETURN_IF_FAILED(); + } + { + QSpan sci = std::as_const(c); // CTAD + static_assert(std::is_same_v<decltype(sci), QSpan<const int, ExpectedExtent>>); + + QCOMPARE_EQ(sci.size(), c_size); + QCOMPARE_EQ(sci.data(), c_data); + + check_nonempty_span(sci, c_size); + RETURN_IF_FAILED(); + } +} + +template <typename C> +void tst_QSpan::from_variable_size_container_impl(C &&c) const +{ + constexpr auto E = q20::dynamic_extent; + from_container_impl<E>(std::forward<C>(c)); +} + +void tst_QSpan::fromArray() const +{ + int ai[] = {42, 84, 168, 336}; + from_container_impl<4>(ai); +} + +void tst_QSpan::fromStdArray() const +{ + std::array<int, 4> ai = {42, 84, 168, 336}; + from_container_impl<4>(ai); +} + +void tst_QSpan::fromStdInitializerList() const +{ + std::initializer_list<int> il = {42, 84, 168, 336}; + + QSpan sci = il; // CTAD + // special case: always deduced as <const int>: + static_assert(std::is_same_v<decltype(sci), QSpan<const int>>); + + QCOMPARE_EQ(sci.size(), qsizetype(il.size())); + QCOMPARE_EQ(sci.data(), il.begin()); + + check_nonempty_span(sci, 4); + RETURN_IF_FAILED(); +} + +void tst_QSpan::fromZeroSizeStdArray() const +{ + std::array<int, 0> ai = {}; + QSpan si = ai; // CTAD + static_assert(std::is_same_v<decltype(si), QSpan<int, 0>>); + QCOMPARE_EQ(si.data(), ai.data()); + + const std::array<int, 0> cai = {}; + QSpan csi = cai; // CTAD + static_assert(std::is_same_v<decltype(csi), QSpan<const int, 0>>); + QCOMPARE_EQ(csi.data(), cai.data()); + + std::array<const int, 0> aci = {}; + QSpan sci = aci; // CTAD + static_assert(std::is_same_v<decltype(sci), QSpan<const int, 0>>); + QCOMPARE_EQ(sci.data(), aci.data()); + + std::array<const int, 0> caci = {}; + QSpan csci = caci; // CTAD + static_assert(std::is_same_v<decltype(csci), QSpan<const int, 0>>); + QCOMPARE_EQ(csci.data(), caci.data()); +} + +void tst_QSpan::fromStdVector() const +{ + std::vector<int> vi = {42, 84, 168, 336}; + from_variable_size_container_impl(vi); +} + +void tst_QSpan::fromQList() const +{ + QList<int> li = {42, 84, 168, 336}; + from_variable_size_container_impl(li); +} + +void tst_QSpan::fromInitList() const +{ + from_variable_size_container_impl(std::initializer_list<int>{42, 84, 168, 336}); + + auto l1 = [](QSpan<const int>){}; + l1({1, 2, 3}); + + auto l2 = [](QSpan<const int, 3>){}; + l2({4, 5, 6}); +} + +#undef RETURN_IF_FAILED + +QTEST_APPLESS_MAIN(tst_QSpan); +#include "tst_qspan.moc" diff --git a/tests/auto/corelib/tools/qstl/CMakeLists.txt b/tests/auto/corelib/tools/qstl/CMakeLists.txt index d39f628cd4..b2f053e6ce 100644 --- a/tests/auto/corelib/tools/qstl/CMakeLists.txt +++ b/tests/auto/corelib/tools/qstl/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qstl.pro. - ##################################################################### ## tst_qstl Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstl LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstl SOURCES tst_qstl.cpp diff --git a/tests/auto/corelib/tools/qstl/tst_qstl.cpp b/tests/auto/corelib/tools/qstl/tst_qstl.cpp index bd344fe43c..43d40bc128 100644 --- a/tests/auto/corelib/tools/qstl/tst_qstl.cpp +++ b/tests/auto/corelib/tools/qstl/tst_qstl.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt b/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt index f9bc77dcc7..fb2e5dc922 100644 --- a/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt +++ b/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qtaggedpointer.pro. - ##################################################################### ## tst_qtaggedpointer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtaggedpointer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtaggedpointer SOURCES tst_qtaggedpointer.cpp diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp index 752bf48d93..a1e61fc3a1 100644 --- a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp +++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/qtaggedpointer.h> @@ -11,6 +11,7 @@ class tst_QTaggedPointer : public QObject private Q_SLOTS: void constExpr(); void construction(); + void assignment(); void dereferenceOperator(); void pointerOperator(); void negationOperator(); @@ -80,6 +81,47 @@ void tst_QTaggedPointer::construction() } } +void tst_QTaggedPointer::assignment() +{ + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QTaggedPointer<int> p2(rawPointer.data(), 0x2); + + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + QCOMPARE(p2.data(), rawPointer.data()); + QCOMPARE(p2.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = p2; + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x0)); +} + class AbstractClass { public: diff --git a/tests/auto/corelib/tools/qtimeline/CMakeLists.txt b/tests/auto/corelib/tools/qtimeline/CMakeLists.txt index 8725b9e255..a43e93990a 100644 --- a/tests/auto/corelib/tools/qtimeline/CMakeLists.txt +++ b/tests/auto/corelib/tools/qtimeline/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qtimeline.pro. - ##################################################################### ## tst_qtimeline Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtimeline LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtimeline SOURCES tst_qtimeline.cpp diff --git a/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp b/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp index d1a1d2c169..3593a65c4e 100644 --- a/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp +++ b/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtTest/private/qpropertytesthelper_p.h> @@ -80,7 +80,7 @@ void tst_QTimeLine::range() timeLine.setStartFrame(5000); QVERIFY(timeLine.currentFrame() > oldValue); timeLine.setFrameRange(0, 500); - QTRY_VERIFY(spy.count() > 1); + QTRY_VERIFY(spy.size() > 1); QVERIFY(timeLine.currentFrame() < oldValue); } @@ -102,7 +102,7 @@ void tst_QTimeLine::currentTime() spy.clear(); timeLine.setCurrentTime(timeLine.duration()/2); timeLine.setCurrentTime(timeLine.duration()/2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QCOMPARE(timeLine.currentTime(), timeLine.duration()/2); timeLine.resume(); @@ -153,10 +153,10 @@ void tst_QTimeLine::bindableCurrentTime() spy.clear(); QProperty<int> referenceCurrentTime(timeLine.duration() / 2); timeLine.bindableCurrentTime().setBinding([&]() { return referenceCurrentTime.value(); }); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); // setting it a second time to check that valueChanged() is emitted only once referenceCurrentTime = timeLine.duration() / 2; - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QCOMPARE(timeLine.currentTime(), timeLine.duration() / 2); @@ -172,7 +172,7 @@ void tst_QTimeLine::bindableCurrentTime() spy.clear(); referenceCurrentTime = 0; QCOMPARE(currentTimeObserver.value(), timeLine.duration()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QTimeLine::duration() @@ -236,7 +236,7 @@ void tst_QTimeLine::frameRate() timeLine.start(); QTest::qWait(timeLine.duration()*2); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - int slowCount = spy.count(); + int slowCount = spy.size(); // Faster!! timeLine.setUpdateInterval(1000 / 100); @@ -245,7 +245,7 @@ void tst_QTimeLine::frameRate() timeLine.start(); QTest::qWait(timeLine.duration()*2); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - QVERIFY2(slowCount < spy.count(), QByteArray::number(spy.count())); + QVERIFY2(slowCount < spy.size(), QByteArray::number(spy.size())); } void tst_QTimeLine::bindableUpdateInterval() @@ -270,7 +270,7 @@ void tst_QTimeLine::bindableUpdateInterval() timeLine.start(); QTest::qWait(timeLine.duration() * 2); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - int slowCount = spy.count(); + int slowCount = spy.size(); // Faster!! updateIntervalReference = 1000 / 100; @@ -279,7 +279,7 @@ void tst_QTimeLine::bindableUpdateInterval() timeLine.start(); QTest::qWait(timeLine.duration() * 2); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - QVERIFY2(slowCount < spy.count(), QByteArray::number(spy.count())); + QVERIFY2(slowCount < spy.size(), QByteArray::number(spy.size())); } void tst_QTimeLine::value() @@ -294,7 +294,7 @@ void tst_QTimeLine::value() QTRY_VERIFY(timeLine.currentValue() > 0); QTRY_COMPARE(timeLine.state(), QTimeLine::NotRunning); QCOMPARE(timeLine.currentValue(), 1.0); - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); // Reverse should decrease the value timeLine.setCurrentTime(100); @@ -380,8 +380,8 @@ void tst_QTimeLine::loopCount() loop.exec(); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(frameChangedSpy.count(), 11); + QCOMPARE(finishedSpy.size(), 1); + QCOMPARE(frameChangedSpy.size(), 11); for (int i = 0; i < 11; ++i) QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), (i+1) % 3); } @@ -390,8 +390,8 @@ void tst_QTimeLine::loopCount() timeLine.start(); loop.exec(); - QCOMPARE(finishedSpy.count(), 2); - QCOMPARE(frameChangedSpy.count(), 22); + QCOMPARE(finishedSpy.size(), 2); + QCOMPARE(frameChangedSpy.size(), 22); for (int i = 11; i < 22; ++i) { QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), 2 - (i+2) % 3); } @@ -456,8 +456,8 @@ void tst_QTimeLine::bindableLoopCount() loop.exec(); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(frameChangedSpy.count(), 11); + QCOMPARE(finishedSpy.size(), 1); + QCOMPARE(frameChangedSpy.size(), 11); for (int i = 0; i < 11; ++i) QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), (i + 1) % 3); } @@ -466,8 +466,8 @@ void tst_QTimeLine::bindableLoopCount() timeLine.start(); loop.exec(); - QCOMPARE(finishedSpy.count(), 2); - QCOMPARE(frameChangedSpy.count(), 22); + QCOMPARE(finishedSpy.size(), 2); + QCOMPARE(frameChangedSpy.size(), 22); for (int i = 11; i < 22; ++i) QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), 2 - (i + 2) % 3); } @@ -636,14 +636,14 @@ void tst_QTimeLine::frameChanged() timeLine.start(); QTest::qWait(timeLine.duration()/2); QCOMPARE(timeLine.state(), QTimeLine::Running); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QTest::qWait(timeLine.duration()); if (timeLine.state() != QTimeLine::NotRunning) QEXPECT_FAIL("", "QTBUG-24796: QTimeLine runs slower than it should", Abort); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - if (spy.count() != 1) + if (spy.size() != 1) QEXPECT_FAIL("", "QTBUG-24796: QTimeLine runs slower than it should", Abort); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); // Test what happens when the frames are all emitted well before duration expires. timeLine.setUpdateInterval(5); @@ -652,7 +652,7 @@ void tst_QTimeLine::frameChanged() timeLine.start(); QTest::qWait(timeLine.duration()*2); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - QCOMPARE(spy.count(), 10); + QCOMPARE(spy.size(), 10); } void tst_QTimeLine::stopped() @@ -665,11 +665,11 @@ void tst_QTimeLine::stopped() timeLine.start(); QTest::qWait(timeLine.duration()*2); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); spy.clear(); timeLine.start(); timeLine.stop(); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); timeLine.setDirection(QTimeLine::Backward); QCOMPARE(timeLine.loopCount(), 1); } @@ -681,13 +681,13 @@ void tst_QTimeLine::finished() QSignalSpy spy(&timeLine, &QTimeLine::finished); QVERIFY(spy.isValid()); timeLine.start(); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(timeLine.state(), QTimeLine::NotRunning); spy.clear(); timeLine.start(); timeLine.stop(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QTimeLine::isRunning() @@ -720,7 +720,7 @@ void tst_QTimeLine::multipleTimeLines() timeLine.start(); timeLineKiller.stop(); QTest::qWait(timeLine.duration()*2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QTimeLine::sineCurve() diff --git a/tests/auto/corelib/tools/qtyperevision/CMakeLists.txt b/tests/auto/corelib/tools/qtyperevision/CMakeLists.txt new file mode 100644 index 0000000000..527156e3c2 --- /dev/null +++ b/tests/auto/corelib/tools/qtyperevision/CMakeLists.txt @@ -0,0 +1,15 @@ +# 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_qtyperevision LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qtyperevision + SOURCES + tst_qtyperevision.cpp + LIBRARIES + Qt::TestPrivate +) diff --git a/tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp b/tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp new file mode 100644 index 0000000000..66c746382a --- /dev/null +++ b/tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp @@ -0,0 +1,202 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> +#include <QtCore/qtyperevision.h> +#include <QtTest/private/qcomparisontesthelper_p.h> + +using namespace Qt::StringLiterals; + +class tst_QTypeRevision : public QObject +{ + Q_OBJECT + +private slots: + void qTypeRevision_data(); + void qTypeRevision(); + void qTypeRevisionTypes(); + void qTypeRevisionComparisonCompiles(); + void qTypeRevisionComparison_data(); + void qTypeRevisionComparison(); +}; + +template<typename Integer> +void compileTestRevisionMajorMinor() +{ + const Integer major = 8; + const Integer minor = 4; + + const QTypeRevision r2 = QTypeRevision::fromVersion(major, minor); + QCOMPARE(r2.majorVersion(), 8); + QCOMPARE(r2.minorVersion(), 4); + + const QTypeRevision r3 = QTypeRevision::fromMajorVersion(major); + QCOMPARE(r3.majorVersion(), 8); + QVERIFY(!r3.hasMinorVersion()); + + const QTypeRevision r4 = QTypeRevision::fromMinorVersion(minor); + QVERIFY(!r4.hasMajorVersion()); + QCOMPARE(r4.minorVersion(), 4); +} + + +template<typename Integer> +void compileTestRevision() +{ + if (std::is_signed<Integer>::value) + compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Signed>(); + else + compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Unsigned>(); + + const Integer value = 0x0510; + const QTypeRevision r = QTypeRevision::fromEncodedVersion(value); + + QCOMPARE(r.majorVersion(), 5); + QCOMPARE(r.minorVersion(), 16); + QCOMPARE(r.toEncodedVersion<Integer>(), value); + + compileTestRevisionMajorMinor<Integer>(); +} + +template<> +void compileTestRevision<qint16>() +{ + compileTestRevisionMajorMinor<quint8>(); +} + +template<> +void compileTestRevision<quint8>() +{ + compileTestRevisionMajorMinor<quint8>(); +} + +template<> +void compileTestRevision<qint8>() +{ + compileTestRevisionMajorMinor<qint8>(); +} + +void tst_QTypeRevision::qTypeRevision_data() +{ + QTest::addColumn<QTypeRevision>("revision"); + QTest::addColumn<bool>("valid"); + QTest::addColumn<int>("major"); + QTest::addColumn<int>("minor"); + + QTest::addRow("Qt revision") << QTypeRevision::fromVersion(QT_VERSION_MAJOR, QT_VERSION_MINOR) + << true << QT_VERSION_MAJOR << QT_VERSION_MINOR; + QTest::addRow("invalid") << QTypeRevision() << false << 0xff << 0xff; + QTest::addRow("major") << QTypeRevision::fromMajorVersion(6) << true << 6 << 0xff; + QTest::addRow("minor") << QTypeRevision::fromMinorVersion(15) << true << 0xff << 15; + QTest::addRow("zero") << QTypeRevision::fromVersion(0, 0) << true << 0 << 0; + + // We're intentionally not testing negative numbers. + // There are asserts against negative numbers in QTypeRevision. + // You must not pass them as major or minor versions, or values. +} + +void tst_QTypeRevision::qTypeRevision() +{ + const QTypeRevision other = QTypeRevision::fromVersion(127, 128); + + QFETCH(QTypeRevision, revision); + + QFETCH(bool, valid); + QFETCH(int, major); + QFETCH(int, minor); + + QCOMPARE(revision.isValid(), valid); + QCOMPARE(revision.majorVersion(), major); + QCOMPARE(revision.minorVersion(), minor); + + QCOMPARE(revision.hasMajorVersion(), QTypeRevision::isValidSegment(major)); + QCOMPARE(revision.hasMinorVersion(), QTypeRevision::isValidSegment(minor)); + + const QTypeRevision copy = QTypeRevision::fromEncodedVersion(revision.toEncodedVersion<int>()); + QCOMPARE(copy, revision); + + QVERIFY(revision != other); + QVERIFY(copy != other); +} + +void tst_QTypeRevision::qTypeRevisionTypes() +{ + compileTestRevision<quint64>(); + compileTestRevision<qint64>(); + + QVERIFY(!QTypeRevision::isValidSegment(0xff)); + QVERIFY(!QTypeRevision::isValidSegment(-1)); + + const QTypeRevision maxRevision = QTypeRevision::fromVersion(254, 254); + QVERIFY(maxRevision.hasMajorVersion()); + QVERIFY(maxRevision.hasMinorVersion()); +} + +void tst_QTypeRevision::qTypeRevisionComparisonCompiles() +{ + QTestPrivate::testAllComparisonOperatorsCompile<QTypeRevision>(); +} + +void tst_QTypeRevision::qTypeRevisionComparison_data() +{ + QTest::addColumn<QTypeRevision>("lhs"); + QTest::addColumn<QTypeRevision>("rhs"); + QTest::addColumn<Qt::strong_ordering>("expectedResult"); + + static auto versionStr = [](QTypeRevision r) { + QByteArray res = r.hasMajorVersion() ? QByteArray::number(r.majorVersion()) + : "x"_ba; + res.append('.'); + res.append(r.hasMinorVersion() ? QByteArray::number(r.minorVersion()) + : "x"_ba); + return res; + }; + + const QTypeRevision revisions[] = { + QTypeRevision::zero(), + QTypeRevision::fromMajorVersion(0), + QTypeRevision::fromVersion(0, 1), + QTypeRevision::fromVersion(0, 20), + QTypeRevision::fromMinorVersion(0), + QTypeRevision(), + QTypeRevision::fromMinorVersion(1), + QTypeRevision::fromMinorVersion(20), + QTypeRevision::fromVersion(1, 0), + QTypeRevision::fromMajorVersion(1), + QTypeRevision::fromVersion(1, 1), + QTypeRevision::fromVersion(1, 20), + QTypeRevision::fromVersion(20, 0), + QTypeRevision::fromMajorVersion(20), + QTypeRevision::fromVersion(20, 1), + QTypeRevision::fromVersion(20, 20), + }; + + const int length = sizeof(revisions) / sizeof(QTypeRevision); + for (int i = 0; i < length; ++i) { + for (int j = i; j < length; ++j) { + const Qt::strong_ordering expectedRes = (i == j) + ? Qt::strong_ordering::equal + : (i < j) ? Qt::strong_ordering::less + : Qt::strong_ordering::greater; + + const auto lhs = revisions[i]; + const auto rhs = revisions[j]; + QTest::addRow("%s_vs_%s", versionStr(lhs).constData(), versionStr(rhs).constData()) + << lhs << rhs << expectedRes; + } + } +} + +void tst_QTypeRevision::qTypeRevisionComparison() +{ + QFETCH(const QTypeRevision, lhs); + QFETCH(const QTypeRevision, rhs); + QFETCH(const Qt::strong_ordering, expectedResult); + + QT_TEST_ALL_COMPARISON_OPS(lhs, rhs, expectedResult); +} + +QTEST_APPLESS_MAIN(tst_QTypeRevision) + +#include "tst_qtyperevision.moc" diff --git a/tests/auto/corelib/tools/quniquehandle/CMakeLists.txt b/tests/auto/corelib/tools/quniquehandle/CMakeLists.txt new file mode 100644 index 0000000000..fe46826f37 --- /dev/null +++ b/tests/auto/corelib/tools/quniquehandle/CMakeLists.txt @@ -0,0 +1,15 @@ +# 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_quniquehandle LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_quniquehandle + SOURCES + tst_quniquehandle.cpp + LIBRARIES + Qt::CorePrivate +) diff --git a/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp b/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp new file mode 100644 index 0000000000..ed46999e73 --- /dev/null +++ b/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp @@ -0,0 +1,308 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <private/quniquehandle_p.h> + +#include <QTest> + +QT_USE_NAMESPACE; + +// clang-format off +namespace GlobalResource { + +std::array<bool, 3> s_resources = { false, false, false }; + +using handle = size_t; +constexpr handle s_invalidHandle = static_cast<handle>(-1); + +handle open() +{ + const auto it = std::find_if(s_resources.begin(), s_resources.end(), + [](bool resource) { + return !resource; + }); + + if (it == s_resources.end()) + return s_invalidHandle; + + *it = true; + + return std::distance(s_resources.begin(), it); +} + +bool open(handle* dest) +{ + const handle resource = open(); + + if (resource == s_invalidHandle) + return false; + + *dest = resource; + return true; +} + +bool close(handle h) +{ + if (h >= s_resources.size()) + return false; // Invalid handle + + if (!s_resources[h]) + return false; // Un-allocated resource + + s_resources[h] = false; + return true; +} + +bool isOpen(handle h) +{ + return s_resources[h]; +} + +void reset() +{ + std::fill(s_resources.begin(), s_resources.end(), false); +} + +bool isReset() +{ + return std::all_of(s_resources.begin(), s_resources.end(), [](bool res) { + return !res; + }); +} + +} // namespace GlobalResource + +struct TestTraits +{ + using Type = GlobalResource::handle; + + static bool close(Type handle) + { + return GlobalResource::close(handle); + } + + static Type invalidValue() noexcept + { + return GlobalResource::s_invalidHandle; + } +}; + +using Handle = QUniqueHandle<TestTraits>; + +class tst_QUniqueHandle : public QObject +{ + Q_OBJECT + +private slots: + + void init() const + { + GlobalResource::reset(); + } + + void cleanup() const + { + QVERIFY(GlobalResource::isReset()); + } + + void defaultConstructor_initializesToInvalidHandle() const + { + const Handle h; + QCOMPARE_EQ(h.get(), TestTraits::invalidValue()); + } + + void constructor_initializesToValid_whenCalledWithValidHandle() const + { + const auto res = GlobalResource::open(); + + const Handle h{ res }; + + QCOMPARE_EQ(h.get(), res); + } + + void copyConstructor_and_assignmentOperator_areDeleted() const + { + static_assert(!std::is_copy_constructible_v<Handle> && !std::is_copy_assignable_v<Handle>); + } + + void moveConstructor_movesOwnershipAndResetsSource() const + { + Handle source{ GlobalResource::open() }; + const Handle dest{ std::move(source) }; + + QVERIFY(!source.isValid()); + QVERIFY(dest.isValid()); + QVERIFY(GlobalResource::isOpen(dest.get())); + } + + void moveAssignment_movesOwnershipAndResetsSource() const + { + Handle source{ GlobalResource::open() }; + Handle dest; + dest = { std::move(source) }; + + QVERIFY(!source.isValid()); + QVERIFY(dest.isValid()); + QVERIFY(GlobalResource::isOpen(dest.get())); + } + + void isValid_returnsFalse_onlyWhenHandleIsInvalid() const + { + const Handle invalid; + QVERIFY(!invalid.isValid()); + + const Handle valid{ GlobalResource::open() }; + QVERIFY(valid.isValid()); + } + + void destructor_callsClose_whenHandleIsValid() + { + { + const Handle h0{ GlobalResource::open() }; + const Handle h1{ GlobalResource::open() }; + const Handle h2{ GlobalResource::open() }; + QVERIFY(!GlobalResource::isReset()); + } + + QVERIFY(GlobalResource::isReset()); + } + + void operatorBool_returnsFalse_onlyWhenHandleIsInvalid() const + { + const Handle invalid; + QVERIFY(!invalid); + + const Handle valid{ GlobalResource::open() }; + QVERIFY(valid); + } + + void get_returnsValue() const + { + const Handle invalid; + QCOMPARE_EQ(invalid.get(), GlobalResource::s_invalidHandle); + + const auto resource = GlobalResource::open(); + const Handle valid{ resource }; + QCOMPARE_EQ(valid.get(), resource); + } + + void reset_resetsPreviousValueAndTakesOwnership() const + { + const auto resource0 = GlobalResource::open(); + const auto resource1 = GlobalResource::open(); + + Handle h1{ resource0 }; + h1.reset(resource1); + + QVERIFY(!GlobalResource::isOpen(resource0)); + QVERIFY(GlobalResource::isOpen(resource1)); + } + + void release_returnsInvalidResource_whenCalledOnInvalidHandle() const + { + Handle h; + QCOMPARE_EQ(h.release(), GlobalResource::s_invalidHandle); + } + + void release_releasesOwnershipAndReturnsResource_whenHandleOwnsObject() const + { + GlobalResource::handle resource{ GlobalResource::open() }; + GlobalResource::handle released{}; + { + Handle h{ resource }; + released = h.release(); + } + QVERIFY(GlobalResource::isOpen(resource)); + QCOMPARE_EQ(resource, released); + + GlobalResource::close(resource); + } + + void swap_swapsOwnership() const + { + const auto resource0 = GlobalResource::open(); + const auto resource1 = GlobalResource::open(); + + Handle h0{ resource0 }; + Handle h1{ resource1 }; + + std::swap(h0, h1); + + QCOMPARE_EQ(h0.get(), resource1); + QCOMPARE_EQ(h1.get(), resource0); + } + + void comparison_behavesAsInt_whenHandleTypeIsInt_data() const + { + QTest::addColumn<int>("lhs"); + QTest::addColumn<int>("rhs"); + + QTest::addRow("lhs == rhs") << 1 << 1; + QTest::addRow("lhs < rhs") << 0 << 1; + QTest::addRow("lhs > rhs") << 1 << 0; + } + + void comparison_behavesAsInt_whenHandleTypeIsInt() const + { + struct IntTraits + { + using Type = int; + + static bool close(Type) + { + return true; + } + + static Type invalidValue() noexcept + { + return INT_MAX; + } + }; + + using Handle = QUniqueHandle<IntTraits>; + + QFETCH(int, lhs); + QFETCH(int, rhs); + + QCOMPARE_EQ(Handle{ lhs } == Handle{ rhs }, lhs == rhs); + QCOMPARE_EQ(Handle{ lhs } != Handle{ rhs }, lhs != rhs); + QCOMPARE_EQ(Handle{ lhs } < Handle{ rhs }, lhs < rhs); + QCOMPARE_EQ(Handle{ lhs } <= Handle{ rhs }, lhs <= rhs); + QCOMPARE_EQ(Handle{ lhs } > Handle{ rhs }, lhs > rhs); + QCOMPARE_EQ(Handle{ lhs } >= Handle{ rhs }, lhs >= rhs); + + QCOMPARE_EQ(Handle{ }, Handle{ }); + } + + void sort_sortsHandles() const + { + const auto resource0 = GlobalResource::open(); + const auto resource1 = GlobalResource::open(); + + QVERIFY(resource1 > resource0); // Precondition of underlying allocator + + Handle h0{ resource0 }; + Handle h1{ resource1 }; + + std::vector<Handle> handles; + handles.push_back(std::move(h1)); + handles.push_back(std::move(h0)); + + std::sort(handles.begin(), handles.end()); + + QCOMPARE_LT(handles.front(), handles.back()); + QCOMPARE_LT(handles.front().get(), handles.back().get()); + } + + void addressOf_returnsAddressOfHandle() const + { + Handle h; + QVERIFY(GlobalResource::open(&h)); + QVERIFY(h.isValid()); + } + +}; + +// clang-format on +QTEST_MAIN(tst_QUniqueHandle) +#include "tst_quniquehandle.moc" diff --git a/tests/auto/corelib/tools/qvarlengtharray/CMakeLists.txt b/tests/auto/corelib/tools/qvarlengtharray/CMakeLists.txt index 481cfab8c1..eccb2634cc 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/CMakeLists.txt +++ b/tests/auto/corelib/tools/qvarlengtharray/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qvarlengtharray.pro. - ##################################################################### ## tst_qvarlengtharray Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qvarlengtharray LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qvarlengtharray SOURCES tst_qvarlengtharray.cpp diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 508f709533..6a92663bc4 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QTest> #include <QVarLengthArray> @@ -7,6 +7,8 @@ #include <qscopeguard.h> #include <qscopedvaluerollback.h> +#include <algorithm> +#include <q20iterator.h> #include <memory> struct Tracker @@ -40,13 +42,31 @@ public: { return !operator==(lhs, rhs); } }; +class NonCopyable +{ + Q_DISABLE_COPY(NonCopyable) + int n; +public: + NonCopyable() : n(0) {} + explicit NonCopyable(int n) : n(n) {} + + friend bool operator==(const NonCopyable &lhs, const NonCopyable &rhs) noexcept + { return lhs.n == rhs.n; } + friend bool operator!=(const NonCopyable &lhs, const NonCopyable &rhs) noexcept + { return !operator==(lhs, rhs); } +}; + class tst_QVarLengthArray : public QObject { Q_OBJECT private slots: void defaultConstructor_int() { defaultConstructor<int>(); } void defaultConstructor_QString() { defaultConstructor<QString>(); } + void sizeConstructor_int() { sizeConstructor<int>(); } + void sizeConstructor_QString() { sizeConstructor<QString>(); } + void sizeConstructor_NonCopyable() { sizeConstructor<NonCopyable>(); } void append(); + void preallocatedSize(); #if QT_DEPRECATED_SINCE(6, 3) void prepend(); #endif @@ -92,9 +112,13 @@ private slots: void remove(); void erase(); + // special cases: + void copesWithCopyabilityOfMoveOnlyVector(); // QTBUG-109745 private: template <typename T> void defaultConstructor(); + template <typename T> + void sizeConstructor(); template <qsizetype N, typename T> void move(T t1, T t2); template <qsizetype N> @@ -124,6 +148,31 @@ void tst_QVarLengthArray::defaultConstructor() } } +template <typename T> +void tst_QVarLengthArray::sizeConstructor() +{ + { + QVarLengthArray<T, 123> vla(0); + QCOMPARE(vla.size(), 0); + QVERIFY(vla.empty()); + QVERIFY(vla.isEmpty()); + QCOMPARE(vla.begin(), vla.end()); + QCOMPARE(vla.capacity(), 123); + } + { + QVarLengthArray<T, 124> vla(124); + QCOMPARE(vla.size(), 124); + QVERIFY(!vla.empty()); + QCOMPARE(vla.capacity(), 124); + } + { + QVarLengthArray<T, 124> vla(125); + QCOMPARE(vla.size(), 125); + QVERIFY(!vla.empty()); + QCOMPARE_GE(vla.capacity(), 125); + } +} + void tst_QVarLengthArray::append() { QVarLengthArray<QString, 2> v; @@ -146,6 +195,15 @@ void tst_QVarLengthArray::append() v2.append(5); } +void tst_QVarLengthArray::preallocatedSize() +{ + // The default is 256: + static_assert(QVarLengthArray<int>::PreallocatedSize == 256); + // Otherwise, whatever was given as template argument: + static_assert(QVarLengthArray<int, 42>::PreallocatedSize == 42); + static_assert(QVarLengthArray<int, 1'000'000>::PreallocatedSize == 1'000'000); +} + #if QT_DEPRECATED_SINCE(6, 3) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED @@ -384,6 +442,17 @@ void tst_QVarLengthArray::appendCausingRealloc() QVarLengthArray<float, 1> d(1); for (int i=0; i<30; i++) d.append(i); + + // Regression test for QTBUG-110412: + constexpr qsizetype InitialCapacity = 10; + QVarLengthArray<float, InitialCapacity> d2(InitialCapacity); + std::iota(d2.begin(), d2.end(), 0.0f); + QCOMPARE_EQ(d2.size(), d2.capacity()); // by construction + float floats[1000]; + std::iota(std::begin(floats), std::end(floats), InitialCapacity + 0.0f); + d2.append(floats, q20::ssize(floats)); + QCOMPARE_EQ(d2.size(), q20::ssize(floats) + InitialCapacity); + QCOMPARE_GE(d2.capacity(), d2.size()); } void tst_QVarLengthArray::appendIsStronglyExceptionSafe() @@ -575,6 +644,12 @@ struct MyBase bool hasMoved() const { return !wasConstructedAt(this); } protected: + void swap(MyBase &other) { + using std::swap; + swap(data, other.data); + swap(isCopy, other.isCopy); + } + MyBase(const MyBase *data, bool isCopy) : data(data), isCopy(isCopy) {} @@ -649,6 +724,14 @@ struct MyMovable return *this; } + void swap(MyMovable &other) noexcept + { + MyBase::swap(other); + std::swap(i, other.i); + } + + friend void swap(MyMovable &lhs, MyMovable &rhs) noexcept { lhs.swap(rhs); } + bool operator==(const MyMovable &other) const { return i == other.i; @@ -664,6 +747,15 @@ struct MyComplex { return i == other.i; } + + void swap(MyComplex &other) noexcept + { + MyBase::swap(other); + std::swap(i, other.i); + } + + friend void swap(MyComplex &lhs, MyComplex &rhs) noexcept { lhs.swap(rhs); } + char i; }; @@ -936,8 +1028,8 @@ void tst_QVarLengthArray::count() // tests size(), count() and length(), since they're the same thing { const QVarLengthArray<int> list; - QCOMPARE(list.length(), 0); - QCOMPARE(list.count(), 0); + QCOMPARE(list.size(), 0); + QCOMPARE(list.size(), 0); QCOMPARE(list.size(), 0); QVERIFY(list.isEmpty()); } @@ -945,8 +1037,8 @@ void tst_QVarLengthArray::count() { QVarLengthArray<int> list; list.append(0); - QCOMPARE(list.length(), 1); - QCOMPARE(list.count(), 1); + QCOMPARE(list.size(), 1); + QCOMPARE(list.size(), 1); QCOMPARE(list.size(), 1); QVERIFY(!list.isEmpty()); } @@ -955,8 +1047,8 @@ void tst_QVarLengthArray::count() QVarLengthArray<int> list; list.append(0); list.append(1); - QCOMPARE(list.length(), 2); - QCOMPARE(list.count(), 2); + QCOMPARE(list.size(), 2); + QCOMPARE(list.size(), 2); QCOMPARE(list.size(), 2); QVERIFY(!list.isEmpty()); } @@ -966,8 +1058,8 @@ void tst_QVarLengthArray::count() list.append(0); list.append(0); list.append(0); - QCOMPARE(list.length(), 3); - QCOMPARE(list.count(), 3); + QCOMPARE(list.size(), 3); + QCOMPARE(list.size(), 3); QCOMPARE(list.size(), 3); QVERIFY(!list.isEmpty()); } @@ -978,23 +1070,23 @@ void tst_QVarLengthArray::count() list.append(0); list.append(0); list.append(0); - QCOMPARE(list.length(), 3); - QCOMPARE(list.count(), 3); + QCOMPARE(list.size(), 3); + QCOMPARE(list.size(), 3); QCOMPARE(list.size(), 3); QVERIFY(!list.isEmpty()); list.removeLast(); - QCOMPARE(list.length(), 2); - QCOMPARE(list.count(), 2); + QCOMPARE(list.size(), 2); + QCOMPARE(list.size(), 2); QCOMPARE(list.size(), 2); QVERIFY(!list.isEmpty()); list.removeLast(); - QCOMPARE(list.length(), 1); - QCOMPARE(list.count(), 1); + QCOMPARE(list.size(), 1); + QCOMPARE(list.size(), 1); QCOMPARE(list.size(), 1); QVERIFY(!list.isEmpty()); list.removeLast(); - QCOMPARE(list.length(), 0); - QCOMPARE(list.count(), 0); + QCOMPARE(list.size(), 0); + QCOMPARE(list.size(), 0); QCOMPARE(list.size(), 0); QVERIFY(list.isEmpty()); } @@ -1033,16 +1125,16 @@ void tst_QVarLengthArray::first() QCOMPARE(list.first(), 27); list.append(1987); QCOMPARE(list.first(), 27); - QCOMPARE(list.length(), 3); + QCOMPARE(list.size(), 3); // remove some, make sure it stays sane list.removeLast(); QCOMPARE(list.first(), 27); - QCOMPARE(list.length(), 2); + QCOMPARE(list.size(), 2); list.removeLast(); QCOMPARE(list.first(), 27); - QCOMPARE(list.length(), 1); + QCOMPARE(list.size(), 1); } void tst_QVarLengthArray::last() @@ -1055,16 +1147,16 @@ void tst_QVarLengthArray::last() QCOMPARE(list.last(), 4); list.append(1987); QCOMPARE(list.last(), 1987); - QCOMPARE(list.length(), 3); + QCOMPARE(list.size(), 3); // remove some, make sure it stays sane list.removeLast(); QCOMPARE(list.last(), 4); - QCOMPARE(list.length(), 2); + QCOMPARE(list.size(), 2); list.removeLast(); QCOMPARE(list.last(), 27); - QCOMPARE(list.length(), 1); + QCOMPARE(list.size(), 1); } void tst_QVarLengthArray::squeeze() @@ -1108,7 +1200,7 @@ void tst_QVarLengthArray::operators() // +=: not provided, emulate //myvla += myvlatwo; - for (const QString &s : qAsConst(myvlatwo)) + for (const QString &s : std::as_const(myvlatwo)) myvla.push_back(s); QCOMPARE(myvla, combined); @@ -1296,6 +1388,17 @@ void tst_QVarLengthArray::insertMove() QCOMPARE(MyBase::copyCount, 0); { + MyMovable m1, m2; + QCOMPARE(MyBase::liveCount, 2); + QCOMPARE(MyBase::copyCount, 0); + using std::swap; + swap(m1, m2); + QCOMPARE(MyBase::liveCount, 2); + QCOMPARE(MyBase::movedCount, 0); + QCOMPARE(MyBase::copyCount, 0); + } + + { QVarLengthArray<MyMovable, 6> vec; MyMovable m1; MyMovable m2; @@ -1640,5 +1743,26 @@ void tst_QVarLengthArray::erase() QCOMPARE(arr, QVarLengthArray<QString>({ "val0" })); } +void tst_QVarLengthArray::copesWithCopyabilityOfMoveOnlyVector() +{ + // std::vector<move-only-type> is_copyable + // (https://quuxplusone.github.io/blog/2020/02/05/vector-is-copyable-except-when-its-not/) + + QVarLengthArray<std::vector<std::unique_ptr<int>>, 2> vla; + vla.emplace_back(42); + vla.emplace_back(43); + vla.emplace_back(44); // goes to the heap + QCOMPARE_EQ(vla.size(), 3); + QCOMPARE_EQ(vla.front().size(), 42U); + QCOMPARE_EQ(vla.front().front(), nullptr); + QCOMPARE_EQ(vla.back().size(), 44U); + + auto moved = std::move(vla); + QCOMPARE_EQ(moved.size(), 3); + QCOMPARE_EQ(moved.front().size(), 42U); + QCOMPARE_EQ(moved.front().front(), nullptr); + QCOMPARE_EQ(moved.back().size(), 44U); +} + QTEST_APPLESS_MAIN(tst_QVarLengthArray) #include "tst_qvarlengtharray.moc" diff --git a/tests/auto/corelib/tools/qversionnumber/CMakeLists.txt b/tests/auto/corelib/tools/qversionnumber/CMakeLists.txt index df07789842..8f6ed66841 100644 --- a/tests/auto/corelib/tools/qversionnumber/CMakeLists.txt +++ b/tests/auto/corelib/tools/qversionnumber/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qversionnumber.pro. - ##################################################################### ## tst_qversionnumber Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qversionnumber LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qversionnumber SOURCES tst_qversionnumber.cpp diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp index cc17188c54..da9dcc9366 100644 --- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp +++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/qversionnumber.h> @@ -53,14 +53,14 @@ private slots: void toString(); void isNull_data(); void isNull(); + void iterators_data(); + void iterators(); + void iteratorsAreDefaultConstructible(); + void valueInitializedIteratorsCompareEqual(); void serialize_data(); void serialize(); void moveSemantics(); void qtVersion(); - void qTypeRevision_data(); - void qTypeRevision(); - void qTypeRevisionTypes(); - void qTypeRevisionComparison(); }; void tst_QVersionNumber::singleInstanceData() @@ -244,6 +244,11 @@ void tst_QVersionNumber::constructorExplicit() QVersionNumber v8 = {4, 5, 6}; QCOMPARE(v7.segments(), v8.segments()); + + QVersionNumber v9(4, 5, 6); + QVersionNumber vA({4, 5, 6}); + + QCOMPARE(v9.segments(), vA.segments()); } void tst_QVersionNumber::constructorCopy_data() @@ -574,6 +579,45 @@ void tst_QVersionNumber::isNull() QCOMPARE(version.isNull(), isNull); } +void tst_QVersionNumber::iterators_data() +{ + singleInstanceData(); +} + +void tst_QVersionNumber::iterators() +{ + QFETCH(const QList<int>, segments); + QFETCH(QVersionNumber, expectedVersion); + + QVERIFY(std::equal(expectedVersion.begin(), expectedVersion.end(), + segments.begin(), segments.end())); + QVERIFY(std::equal(std::as_const(expectedVersion).begin(), std::as_const(expectedVersion).end(), + segments.begin(), segments.end())); + QVERIFY(std::equal(expectedVersion.cbegin(), expectedVersion.cend(), + segments.cbegin(), segments.cend())); + QVERIFY(std::equal(expectedVersion.rbegin(), expectedVersion.rend(), + segments.rbegin(), segments.rend())); + QVERIFY(std::equal(std::as_const(expectedVersion).rbegin(), std::as_const(expectedVersion).rend(), + segments.rbegin(), segments.rend())); + QVERIFY(std::equal(expectedVersion.crbegin(), expectedVersion.crend(), + segments.crbegin(), segments.crend())); +} + +void tst_QVersionNumber::iteratorsAreDefaultConstructible() +{ + static_assert(std::is_default_constructible_v<QVersionNumber::const_iterator>); + [[maybe_unused]] QVersionNumber::const_iterator ci; + [[maybe_unused]] QVersionNumber::const_reverse_iterator cri; +} + +void tst_QVersionNumber::valueInitializedIteratorsCompareEqual() +{ + QVersionNumber::const_iterator it = {}, jt = {}; + QCOMPARE_EQ(it, jt); + QVersionNumber::const_reverse_iterator rit = {}, rjt = {}; + QCOMPARE_EQ(rit, rjt); +} + void tst_QVersionNumber::serialize_data() { singleInstanceData(); @@ -665,153 +709,6 @@ void tst_QVersionNumber::qtVersion() QCOMPARE(v.toString(), QString(qVersion())); } -template<typename Integer> -void compileTestRevisionMajorMinor() -{ - const Integer major = 8; - const Integer minor = 4; - - const QTypeRevision r2 = QTypeRevision::fromVersion(major, minor); - QCOMPARE(r2.majorVersion(), 8); - QCOMPARE(r2.minorVersion(), 4); - - const QTypeRevision r3 = QTypeRevision::fromMajorVersion(major); - QCOMPARE(r3.majorVersion(), 8); - QVERIFY(!r3.hasMinorVersion()); - - const QTypeRevision r4 = QTypeRevision::fromMinorVersion(minor); - QVERIFY(!r4.hasMajorVersion()); - QCOMPARE(r4.minorVersion(), 4); -} - - -template<typename Integer> -void compileTestRevision() -{ - if (std::is_signed<Integer>::value) - compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Signed>(); - else - compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Unsigned>(); - - const Integer value = 0x0510; - const QTypeRevision r = QTypeRevision::fromEncodedVersion(value); - - QCOMPARE(r.majorVersion(), 5); - QCOMPARE(r.minorVersion(), 16); - QCOMPARE(r.toEncodedVersion<Integer>(), value); - - compileTestRevisionMajorMinor<Integer>(); -} - -template<> -void compileTestRevision<qint16>() -{ - compileTestRevisionMajorMinor<quint8>(); -} - -template<> -void compileTestRevision<quint8>() -{ - compileTestRevisionMajorMinor<quint8>(); -} - -template<> -void compileTestRevision<qint8>() -{ - compileTestRevisionMajorMinor<qint8>(); -} - -void tst_QVersionNumber::qTypeRevision_data() -{ - QTest::addColumn<QTypeRevision>("revision"); - QTest::addColumn<bool>("valid"); - QTest::addColumn<int>("major"); - QTest::addColumn<int>("minor"); - - QTest::addRow("Qt revision") << QTypeRevision::fromVersion(QT_VERSION_MAJOR, QT_VERSION_MINOR) - << true << QT_VERSION_MAJOR << QT_VERSION_MINOR; - QTest::addRow("invalid") << QTypeRevision() << false << 0xff << 0xff; - QTest::addRow("major") << QTypeRevision::fromMajorVersion(6) << true << 6 << 0xff; - QTest::addRow("minor") << QTypeRevision::fromMinorVersion(15) << true << 0xff << 15; - QTest::addRow("zero") << QTypeRevision::fromVersion(0, 0) << true << 0 << 0; - - // We're intentionally not testing negative numbers. - // There are asserts against negative numbers in QTypeRevision. - // You must not pass them as major or minor versions, or values. -} - -void tst_QVersionNumber::qTypeRevision() -{ - const QTypeRevision other = QTypeRevision::fromVersion(127, 128); - - QFETCH(QTypeRevision, revision); - - QFETCH(bool, valid); - QFETCH(int, major); - QFETCH(int, minor); - - QCOMPARE(revision.isValid(), valid); - QCOMPARE(revision.majorVersion(), major); - QCOMPARE(revision.minorVersion(), minor); - - QCOMPARE(revision.hasMajorVersion(), QTypeRevision::isValidSegment(major)); - QCOMPARE(revision.hasMinorVersion(), QTypeRevision::isValidSegment(minor)); - - const QTypeRevision copy = QTypeRevision::fromEncodedVersion(revision.toEncodedVersion<int>()); - QCOMPARE(copy, revision); - - QVERIFY(revision != other); - QVERIFY(copy != other); -} - -void tst_QVersionNumber::qTypeRevisionTypes() -{ - compileTestRevision<quint64>(); - compileTestRevision<qint64>(); - - QVERIFY(!QTypeRevision::isValidSegment(0xff)); - QVERIFY(!QTypeRevision::isValidSegment(-1)); - - const QTypeRevision maxRevision = QTypeRevision::fromVersion(254, 254); - QVERIFY(maxRevision.hasMajorVersion()); - QVERIFY(maxRevision.hasMinorVersion()); -} - -void tst_QVersionNumber::qTypeRevisionComparison() -{ - const QTypeRevision revisions[] = { - QTypeRevision::zero(), - QTypeRevision::fromMajorVersion(0), - QTypeRevision::fromVersion(0, 1), - QTypeRevision::fromVersion(0, 20), - QTypeRevision::fromMinorVersion(0), - QTypeRevision(), - QTypeRevision::fromMinorVersion(1), - QTypeRevision::fromMinorVersion(20), - QTypeRevision::fromVersion(1, 0), - QTypeRevision::fromMajorVersion(1), - QTypeRevision::fromVersion(1, 1), - QTypeRevision::fromVersion(1, 20), - QTypeRevision::fromVersion(20, 0), - QTypeRevision::fromMajorVersion(20), - QTypeRevision::fromVersion(20, 1), - QTypeRevision::fromVersion(20, 20), - }; - - const int length = sizeof(revisions) / sizeof(QTypeRevision); - - for (int i = 0; i < length; ++i) { - for (int j = 0; j < length; ++j) { - QCOMPARE(revisions[i] == revisions[j], i == j); - QCOMPARE(revisions[i] != revisions[j], i != j); - QCOMPARE(revisions[i] < revisions[j], i < j); - QCOMPARE(revisions[i] > revisions[j], i > j); - QCOMPARE(revisions[i] <= revisions[j], i <= j); - QCOMPARE(revisions[i] >= revisions[j], i >= j); - } - } -} - QTEST_APPLESS_MAIN(tst_QVersionNumber) #include "tst_qversionnumber.moc" |