diff options
Diffstat (limited to 'tests/auto/corelib/tools/qmap/tst_qmap.cpp')
-rw-r--r-- | tests/auto/corelib/tools/qmap/tst_qmap.cpp | 1241 |
1 files changed, 1033 insertions, 208 deletions
diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index d8be138c0e..6950dcf705 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -1,34 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qmap.h> #include <QTest> + #include <QDebug> +#include <QScopeGuard> + +using namespace Qt::StringLiterals; QT_WARNING_DISABLE_DEPRECATED @@ -47,6 +26,7 @@ private slots: void beginEnd(); void firstLast(); void key(); + void value(); void swap(); @@ -61,8 +41,13 @@ private slots: void take(); void iterators(); + void multimapIterators(); + void iteratorsInEmptyMap(); void keyIterator(); + void multimapKeyIterator(); void keyValueIterator(); + void multimapKeyValueIterator(); + void keyValueIteratorInEmptyMap(); void keys_values_uniqueKeys(); void qmultimap_specific(); @@ -78,6 +63,16 @@ private slots: void testInsertMultiWithHint(); void eraseValidIteratorOnSharedMap(); void removeElementsInMap(); + void toStdMap(); + + void multiMapStoresInReverseInsertionOrder(); + + // Tests for deprecated APIs. +#if QT_DEPRECATED_SINCE(6, 0) + void deprecatedInsertMulti(); + void deprecatedIteratorApis(); + void deprecatedInsert(); +#endif // QT_DEPRECATED_SINCE(6, 0) }; struct IdentityTracker { @@ -114,6 +109,7 @@ public: int MyClass::count = 0; typedef QMap<QString, MyClass> MyMap; +typedef QMultiMap<QString, MyClass> MyMultiMap; QDebug operator << (QDebug d, const MyClass &c) { d << c.str; @@ -176,13 +172,21 @@ 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); + QCOMPARE(map2.size(), 0); + QVERIFY(!map.isDetached()); + QVERIFY(!map2.isDetached()); // detach map2["Hallo"] = MyClass( "Fritz" ); - QCOMPARE( map.count(), 0 ); - QCOMPARE( map2.count(), 1 ); + QCOMPARE( map.size(), 0 ); + QCOMPARE( map.size(), 0 ); + QCOMPARE( map2.size(), 1 ); + QCOMPARE( map2.size(), 1 ); + QVERIFY(!map.isDetached()); #ifndef Q_CC_SUN QCOMPARE( MyClass::count, 1 ); #endif @@ -192,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") ); @@ -204,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") ); @@ -212,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 @@ -288,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 ); { @@ -316,6 +320,45 @@ void tst_QMap::count() QCOMPARE( MyClass::count, 0 ); } QCOMPARE( MyClass::count, 0 ); + + { + QMultiMap<int, MyClass> map; + QMultiMap<int, MyClass> map2(map); + QCOMPARE(map.size(), 0); + QCOMPARE(map2.size(), 0); + QCOMPARE(MyClass::count, 0); + QCOMPARE(map.count(1), 0); + QCOMPARE(map.size(), 0); + QCOMPARE(map2.size(), 0); + QVERIFY(!map.isDetached()); + QVERIFY(!map2.isDetached()); + + // detach + map2.insert(0, MyClass("value0")); + QCOMPARE(map.size(), 0); + 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.size(), 3); + QCOMPARE(MyClass::count, 3); + + map2.insert(0, MyClass("value0_1")); + map2.insert(0, MyClass("value0_2")); + QCOMPARE(map2.size(), 5); + QCOMPARE(map2.count(0), 3); + QCOMPARE(MyClass::count, 5); + + map2.clear(); + QCOMPARE(map2.size(), 0); + QCOMPARE(MyClass::count, 0); + + } + QCOMPARE(MyClass::count, 0); } void tst_QMap::clear() @@ -323,18 +366,40 @@ void tst_QMap::clear() { MyMap map; map.clear(); - QVERIFY( map.isEmpty() ); + QVERIFY(map.isEmpty()); + QVERIFY(!map.isDetached()); map.insert( "key", MyClass( "value" ) ); + QVERIFY(!map.isEmpty()); map.clear(); - QVERIFY( map.isEmpty() ); + QVERIFY(map.isEmpty()); map.insert( "key0", MyClass( "value0" ) ); map.insert( "key0", MyClass( "value1" ) ); map.insert( "key1", MyClass( "value2" ) ); + QVERIFY(!map.isEmpty()); map.clear(); sanityCheckTree(map, __LINE__); - QVERIFY( map.isEmpty() ); + QVERIFY(map.isEmpty()); } - QCOMPARE( MyClass::count, int(0) ); + QCOMPARE(MyClass::count, int(0)); + + { + MyMultiMap map; + map.clear(); + QVERIFY(map.isEmpty()); + QVERIFY(!map.isDetached()); + map.insert( "key", MyClass( "value" ) ); + QVERIFY(!map.isEmpty()); + map.clear(); + QVERIFY(map.isEmpty()); + map.insert( "key0", MyClass( "value0" ) ); + map.insert( "key0", MyClass( "value1" ) ); + map.insert( "key1", MyClass( "value2" ) ); + QVERIFY(!map.isEmpty()); + map.clear(); + sanityCheckTree(map, __LINE__); + QVERIFY(map.isEmpty()); + } + QCOMPARE(MyClass::count, int(0)); } void tst_QMap::beginEnd() @@ -370,7 +435,12 @@ void tst_QMap::beginEnd() // detach map2.insert( "2", "c" ); QVERIFY( map.constBegin() == map.constBegin() ); - QVERIFY( map.constBegin() != map2.constBegin() ); + + // comparing iterators between two different std::map is UB (and raises an + // assertion failure with MSVC debug-mode iterators), so we compare the + // elements' addresses. + QVERIFY(&map.constBegin().key() != &map2.constBegin().key()); + QVERIFY(&map.constBegin().value() != &map2.constBegin().value()); } void tst_QMap::firstLast() @@ -409,6 +479,7 @@ void tst_QMap::key() QMap<QString, int> map1; QCOMPARE(map1.key(1), QString()); QCOMPARE(map1.key(1, def), def); + QVERIFY(!map1.isDetached()); map1.insert("one", 1); QCOMPARE(map1.key(1), QLatin1String("one")); @@ -439,6 +510,7 @@ void tst_QMap::key() QMap<int, QString> map2; QCOMPARE(map2.key("one"), 0); QCOMPARE(map2.key("one", def), def); + QVERIFY(!map2.isDetached()); map2.insert(1, "one"); QCOMPARE(map2.key("one"), 1); @@ -470,6 +542,82 @@ void tst_QMap::key() QCOMPARE(map2.key("zero"), 0); QCOMPARE(map2.key("zero", def), 0); } + + { + int def = -1; + QMultiMap<int, QString> multiMap; + QCOMPARE(multiMap.key("value0"), 0); + QCOMPARE(multiMap.key("value0", def), def); + QVERIFY(!multiMap.isDetached()); + + multiMap.insert(1, "value1"); + multiMap.insert(2, "value2"); + multiMap.insert(1, "value1_1"); + + QCOMPARE(multiMap.key("value1"), 1); + QCOMPARE(multiMap.key("value1", def), 1); + QCOMPARE(multiMap.key("value1_1"), 1); + QCOMPARE(multiMap.key("value2"), 2); + QCOMPARE(multiMap.key("value3"), 0); + QCOMPARE(multiMap.key("value3", def), def); + } +} + +void tst_QMap::value() +{ + const QString def = "default value"; + { + QMap<int, QString> map; + QCOMPARE(map.value(1), QString()); + QCOMPARE(map.value(1, def), def); + QVERIFY(!map.isDetached()); + + map.insert(1, "value1"); + QCOMPARE(map.value(1), "value1"); + QCOMPARE(map[1], "value1"); + QCOMPARE(map.value(2), QString()); + QCOMPARE(map.value(2, def), def); + QCOMPARE(map[2], QString()); + QCOMPARE(map.size(), 2); + + map.insert(2, "value2"); + QCOMPARE(map.value(2), "value2"); + QCOMPARE(map[2], "value2"); + + map.insert(1, "value3"); + QCOMPARE(map.value(1), "value3"); + QCOMPARE(map.value(1, def), "value3"); + QCOMPARE(map[1], "value3"); + + const QMap<int, QString> constMap; + QVERIFY(!constMap.isDetached()); + QCOMPARE(constMap.value(1, def), def); + QCOMPARE(constMap[1], QString()); + QCOMPARE(constMap.size(), 0); + QVERIFY(!constMap.isDetached()); + } + { + QMultiMap<int, QString> map; + QCOMPARE(map.value(1), QString()); + QCOMPARE(map.value(1, def), def); + QVERIFY(!map.isDetached()); + + map.insert(1, "value1"); + QCOMPARE(map.value(1), "value1"); + QCOMPARE(map.value(2), QString()); + QCOMPARE(map.value(2, def), def); + + map.insert(2, "value2"); + QCOMPARE(map.value(2), "value2"); + + map.insert(1, "value3"); + // If multiple values exist, the most recently added is returned. + QCOMPARE(map.value(1), "value3"); + QCOMPARE(map.value(1, def), "value3"); + + map.remove(1, "value3"); + QCOMPARE(map.value(1), "value1"); + } } void tst_QMap::swap() @@ -492,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: @@ -524,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"); @@ -532,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"); @@ -548,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)); } @@ -562,64 +716,135 @@ void tst_QMap::operator_eq() } } -void tst_QMap::empty() +template <typename T> +void emptyTestMethod() { - QMap<int, QString> map1; + T map; - QVERIFY(map1.isEmpty()); + QVERIFY(map.isEmpty()); + QVERIFY(map.empty()); + QVERIFY(!map.isDetached()); - map1.insert(1, "one"); - QVERIFY(!map1.isEmpty()); + map.insert(1, "one"); + QVERIFY(!map.isEmpty()); + QVERIFY(!map.empty()); - map1.clear(); - QVERIFY(map1.isEmpty()); + map.clear(); + QVERIFY(map.isEmpty()); + QVERIFY(map.empty()); +} + +void tst_QMap::empty() +{ + emptyTestMethod<QMap<int, QString>>(); + if (QTest::currentTestFailed()) + return; + emptyTestMethod<QMultiMap<int, QString>>(); } void tst_QMap::contains() { - QMap<int, QString> map1; - int i; + { + QMap<int, QString> map1; + int i; + + QVERIFY(!map1.contains(1)); + QVERIFY(!map1.isDetached()); - map1.insert(1, "one"); - QVERIFY(map1.contains(1)); + map1.insert(1, "one"); + QVERIFY(map1.contains(1)); - for(i=2; i < 100; ++i) - map1.insert(i, "teststring"); - for(i=99; i > 1; --i) - QVERIFY(map1.contains(i)); + for (i = 2; i < 100; ++i) + map1.insert(i, "teststring"); + for (i = 99; i > 1; --i) + QVERIFY(map1.contains(i)); - map1.remove(43); - QVERIFY(!map1.contains(43)); + map1.remove(43); + QVERIFY(!map1.contains(43)); + } + + { + QMultiMap<int, QString> multiMap; + QVERIFY(!multiMap.contains(1)); + QVERIFY(!multiMap.contains(1, "value1")); + QVERIFY(!multiMap.isDetached()); + + multiMap.insert(1, "value1"); + multiMap.insert(2, "value2"); + multiMap.insert(1, "value1_1"); + + QVERIFY(multiMap.contains(1)); + QVERIFY(multiMap.contains(1, "value1")); + QVERIFY(multiMap.contains(1, "value1_1")); + QVERIFY(multiMap.contains(2)); + QVERIFY(multiMap.contains(2, "value2")); + QVERIFY(!multiMap.contains(2, "invalid_value")); + + QVERIFY(!multiMap.contains(3)); + multiMap.insert(3, "value3"); + QVERIFY(multiMap.contains(3)); + + multiMap.remove(3); + QVERIFY(!multiMap.contains(3)); + } } void tst_QMap::find() { - QMultiMap<int, QString> map1; + { + const QMap<int, QString> constMap; + QCOMPARE(constMap.find(1), constMap.end()); + QVERIFY(!constMap.isDetached()); + + QMap<int, QString> map; + QCOMPARE(map.find(1), map.end()); + + map.insert(1, "value1"); + map.insert(2, "value2"); + map.insert(5, "value5"); + map.insert(1, "value0"); + + QCOMPARE(map.find(1).value(), u"value0"); + QCOMPARE(map.find(5).value(), u"value5"); + QCOMPARE(map.find(2).value(), u"value2"); + QCOMPARE(map.find(4), map.end()); + } + + const QMultiMap<int, QString> constMap; + QCOMPARE(constMap.find(1), constMap.end()); + QCOMPARE(constMap.find(1, "value"), constMap.end()); + QVERIFY(!constMap.isDetached()); + + QMultiMap<int, QString> map; QString testString="Teststring %0"; QString compareString; int i,count=0; - QVERIFY(map1.find(1) == map1.end()); + QCOMPARE(map.find(1), map.end()); + QCOMPARE(map.find(1, "value1"), map.end()); - map1.insert(1,"Mensch"); - map1.insert(1,"Mayer"); - map1.insert(2,"Hej"); + map.insert(1,"Mensch"); + map.insert(1,"Mayer"); + map.insert(2,"Hej"); - QCOMPARE(map1.find(1).value(), QLatin1String("Mayer")); - QCOMPARE(map1.find(2).value(), QLatin1String("Hej")); + QCOMPARE(map.find(1).value(), QLatin1String("Mayer")); + QCOMPARE(map.find(2).value(), QLatin1String("Hej")); + QCOMPARE(map.find(1, "Mensch").value(), QLatin1String("Mensch")); + QCOMPARE(map.find(1, "Unknown Value"), map.end()); - for(i = 3; i < 10; ++i) { + for (i = 3; i < 10; ++i) { compareString = testString.arg(i); - map1.insertMulti(4, compareString); - QCOMPARE(map1.count(4), i - 2); + map.insert(4, compareString); + QCOMPARE(map.count(4), i - 2); } - QMultiMap<int, QString>::const_iterator it=map1.constFind(4); + QMultiMap<int, QString>::iterator it = map.find(4); - for(i = 9; i > 2 && it != map1.constEnd() && it.key() == 4; --i) { + for (i = 9; i > 2 && it != map.end() && it.key() == 4; --i) { compareString = testString.arg(i); QVERIFY(it.value() == compareString); + QCOMPARE(map.find(4, compareString), it); ++it; ++count; } @@ -628,32 +853,53 @@ void tst_QMap::find() void tst_QMap::constFind() { - QMultiMap<int, QString> map1; + { + QMap<int, QString> map; + QCOMPARE(map.constFind(1), map.constEnd()); + QVERIFY(!map.isDetached()); + + map.insert(1, "value1"); + map.insert(2, "value2"); + map.insert(5, "value5"); + map.insert(1, "value0"); + + QCOMPARE(map.constFind(1).value(), QLatin1String("value0")); + QCOMPARE(map.constFind(5).value(), QLatin1String("value5")); + QCOMPARE(map.constFind(2).value(), QLatin1String("value2")); + QCOMPARE(map.constFind(4), map.constEnd()); + } + + QMultiMap<int, QString> map; QString testString="Teststring %0"; QString compareString; int i,count=0; - QVERIFY(map1.constFind(1) == map1.constEnd()); + QCOMPARE(map.constFind(1), map.constEnd()); + QCOMPARE(map.constFind(1, "value"), map.constEnd()); + QVERIFY(!map.isDetached()); - map1.insert(1,"Mensch"); - map1.insert(1,"Mayer"); - map1.insert(2,"Hej"); + map.insert(1,"Mensch"); + map.insert(1,"Mayer"); + map.insert(2,"Hej"); - QVERIFY(map1.constFind(4) == map1.constEnd()); + QVERIFY(map.constFind(4) == map.constEnd()); - QCOMPARE(map1.constFind(1).value(), QLatin1String("Mayer")); - QCOMPARE(map1.constFind(2).value(), QLatin1String("Hej")); + QCOMPARE(map.constFind(1).value(), QLatin1String("Mayer")); + QCOMPARE(map.constFind(2).value(), QLatin1String("Hej")); + QCOMPARE(map.constFind(1, "Mensch").value(), QLatin1String("Mensch")); + QCOMPARE(map.constFind(1, "Invalid Value"), map.constEnd()); - for(i = 3; i < 10; ++i) { + for (i = 3; i < 10; ++i) { compareString = testString.arg(i); - map1.insertMulti(4, compareString); + map.insert(4, compareString); } - QMultiMap<int, QString>::const_iterator it=map1.constFind(4); + QMultiMap<int, QString>::const_iterator it = map.constFind(4); - for(i = 9; i > 2 && it != map1.constEnd() && it.key() == 4; --i) { + for (i = 9; i > 2 && it != map.constEnd() && it.key() == 4; --i) { compareString = testString.arg(i); QVERIFY(it.value() == compareString); + QCOMPARE(map.constFind(4, compareString), it); ++it; ++count; } @@ -662,58 +908,128 @@ void tst_QMap::constFind() void tst_QMap::lowerUpperBound() { - QMultiMap<int, QString> map1; + { + const QMap<int, QString> emptyConstMap; + QCOMPARE(emptyConstMap.lowerBound(1), emptyConstMap.constEnd()); + QCOMPARE(emptyConstMap.upperBound(1), emptyConstMap.constEnd()); + QVERIFY(!emptyConstMap.isDetached()); + + const QMap<int, QString> constMap { qMakePair(1, "one"), + qMakePair(5, "five"), + qMakePair(10, "ten") }; + + QCOMPARE(constMap.lowerBound(-1).key(), 1); + QCOMPARE(constMap.lowerBound(1).key(), 1); + QCOMPARE(constMap.lowerBound(3).key(), 5); + QCOMPARE(constMap.lowerBound(12), constMap.constEnd()); + + QCOMPARE(constMap.upperBound(-1).key(), 1); + QCOMPARE(constMap.upperBound(1).key(), 5); + QCOMPARE(constMap.upperBound(3).key(), 5); + QCOMPARE(constMap.upperBound(12), constMap.constEnd()); + + QMap<int, QString> map; + + map.insert(1, "one"); + map.insert(5, "five"); + map.insert(10, "ten"); + map.insert(3, "three"); + map.insert(7, "seven"); + + QCOMPARE(map.lowerBound(0).key(), 1); + QCOMPARE(map.lowerBound(1).key(), 1); + QCOMPARE(map.lowerBound(2).key(), 3); + QCOMPARE(map.lowerBound(3).key(), 3); + QCOMPARE(map.lowerBound(4).key(), 5); + QCOMPARE(map.lowerBound(5).key(), 5); + QCOMPARE(map.lowerBound(6).key(), 7); + QCOMPARE(map.lowerBound(7).key(), 7); + QCOMPARE(map.lowerBound(10).key(), 10); + QCOMPARE(map.lowerBound(999), map.end()); + + QCOMPARE(map.upperBound(0).key(), 1); + QCOMPARE(map.upperBound(1).key(), 3); + QCOMPARE(map.upperBound(2).key(), 3); + QCOMPARE(map.upperBound(3).key(), 5); + QCOMPARE(map.upperBound(7).key(), 10); + QCOMPARE(map.upperBound(10), map.end()); + QCOMPARE(map.upperBound(999), map.end()); + } - map1.insert(1, "one"); - map1.insert(5, "five"); - map1.insert(10, "ten"); + const QMultiMap<int, QString> emptyConstMap; + QCOMPARE(emptyConstMap.lowerBound(1), emptyConstMap.constEnd()); + QCOMPARE(emptyConstMap.upperBound(1), emptyConstMap.constEnd()); + QVERIFY(!emptyConstMap.isDetached()); + const QMultiMap<int, QString> constMap { qMakePair(1, "one"), + qMakePair(5, "five"), + qMakePair(10, "ten") }; + + QCOMPARE(constMap.lowerBound(-1).key(), 1); + QCOMPARE(constMap.lowerBound(1).key(), 1); + QCOMPARE(constMap.lowerBound(3).key(), 5); + QCOMPARE(constMap.lowerBound(12), constMap.constEnd()); + + QCOMPARE(constMap.upperBound(-1).key(), 1); + QCOMPARE(constMap.upperBound(1).key(), 5); + QCOMPARE(constMap.upperBound(3).key(), 5); + QCOMPARE(constMap.upperBound(12), constMap.constEnd()); + + QMultiMap<int, QString> map; + + map.insert(1, "one"); + map.insert(5, "five"); + map.insert(10, "ten"); //Copied from documentation - QCOMPARE(map1.upperBound(0).key(), 1); // returns iterator to (1, "one") - QCOMPARE(map1.upperBound(1).key(), 5); // returns iterator to (5, "five") - QCOMPARE(map1.upperBound(2).key(), 5); // returns iterator to (5, "five") - QVERIFY(map1.upperBound(10) == map1.end()); // returns end() - QVERIFY(map1.upperBound(999) == map1.end()); // returns end() - - QCOMPARE(map1.lowerBound(0).key(), 1); // returns iterator to (1, "one") - QCOMPARE(map1.lowerBound(1).key(), 1); // returns iterator to (1, "one") - QCOMPARE(map1.lowerBound(2).key(), 5); // returns iterator to (5, "five") - QCOMPARE(map1.lowerBound(10).key(), 10); // returns iterator to (10, "ten") - QVERIFY(map1.lowerBound(999) == map1.end()); // returns end() - - map1.insert(3, "three"); - map1.insert(7, "seven"); - map1.insertMulti(7, "seven_2"); - - QCOMPARE(map1.upperBound(0).key(), 1); - QCOMPARE(map1.upperBound(1).key(), 3); - QCOMPARE(map1.upperBound(2).key(), 3); - QCOMPARE(map1.upperBound(3).key(), 5); - QCOMPARE(map1.upperBound(7).key(), 10); - QVERIFY(map1.upperBound(10) == map1.end()); - QVERIFY(map1.upperBound(999) == map1.end()); - - QCOMPARE(map1.lowerBound(0).key(), 1); - QCOMPARE(map1.lowerBound(1).key(), 1); - QCOMPARE(map1.lowerBound(2).key(), 3); - QCOMPARE(map1.lowerBound(3).key(), 3); - QCOMPARE(map1.lowerBound(4).key(), 5); - QCOMPARE(map1.lowerBound(5).key(), 5); - QCOMPARE(map1.lowerBound(6).key(), 7); - QCOMPARE(map1.lowerBound(7).key(), 7); - QCOMPARE(map1.lowerBound(6).value(), QLatin1String("seven_2")); - QCOMPARE(map1.lowerBound(7).value(), QLatin1String("seven_2")); - QCOMPARE((++map1.lowerBound(6)).value(), QLatin1String("seven")); - QCOMPARE((++map1.lowerBound(7)).value(), QLatin1String("seven")); - QCOMPARE(map1.lowerBound(10).key(), 10); - QVERIFY(map1.lowerBound(999) == map1.end()); + QCOMPARE(map.upperBound(0).key(), 1); // returns iterator to (1, "one") + QCOMPARE(map.upperBound(1).key(), 5); // returns iterator to (5, "five") + QCOMPARE(map.upperBound(2).key(), 5); // returns iterator to (5, "five") + QVERIFY(map.upperBound(10) == map.end()); // returns end() + QVERIFY(map.upperBound(999) == map.end()); // returns end() + + QCOMPARE(map.lowerBound(0).key(), 1); // returns iterator to (1, "one") + QCOMPARE(map.lowerBound(1).key(), 1); // returns iterator to (1, "one") + QCOMPARE(map.lowerBound(2).key(), 5); // returns iterator to (5, "five") + QCOMPARE(map.lowerBound(10).key(), 10); // returns iterator to (10, "ten") + QVERIFY(map.lowerBound(999) == map.end()); // returns end() + + map.insert(3, "three"); + map.insert(7, "seven"); + map.insert(7, "seven_2"); + + QCOMPARE(map.upperBound(0).key(), 1); + QCOMPARE(map.upperBound(1).key(), 3); + QCOMPARE(map.upperBound(2).key(), 3); + QCOMPARE(map.upperBound(3).key(), 5); + QCOMPARE(map.upperBound(7).key(), 10); + QVERIFY(map.upperBound(10) == map.end()); + QVERIFY(map.upperBound(999) == map.end()); + + QCOMPARE(map.lowerBound(0).key(), 1); + QCOMPARE(map.lowerBound(1).key(), 1); + QCOMPARE(map.lowerBound(2).key(), 3); + QCOMPARE(map.lowerBound(3).key(), 3); + QCOMPARE(map.lowerBound(4).key(), 5); + QCOMPARE(map.lowerBound(5).key(), 5); + QCOMPARE(map.lowerBound(6).key(), 7); + QCOMPARE(map.lowerBound(7).key(), 7); + QCOMPARE(map.lowerBound(6).value(), QLatin1String("seven_2")); + QCOMPARE(map.lowerBound(7).value(), QLatin1String("seven_2")); + QCOMPARE((++map.lowerBound(6)).value(), QLatin1String("seven")); + QCOMPARE((++map.lowerBound(7)).value(), QLatin1String("seven")); + QCOMPARE(map.lowerBound(10).key(), 10); + QVERIFY(map.lowerBound(999) == map.end()); } void tst_QMap::mergeCompare() { - QMultiMap<int, QString> map1, map2, map3, map1b, map2b; + QMultiMap<int, QString> map1, map2, map3, map1b, map2b, map4; + + // unite with an empty map does nothing + map1.unite(map2); + QVERIFY(!map1.isDetached()); map1.insert(1,"ett"); map1.insert(3,"tre"); @@ -743,18 +1059,43 @@ void tst_QMap::mergeCompare() map3.insert(4, "fyra"); map3.insert(5, "fem"); - QVERIFY(map1 == map3); + QCOMPARE(map1, map3); + + map4.unite(map3); + QCOMPARE(map4, map3); } void tst_QMap::take() { - QMap<int, QString> map; + { + QMap<int, QString> map; + QCOMPARE(map.take(1), QString()); + QVERIFY(!map.isDetached()); - map.insert(2, "zwei"); - map.insert(3, "drei"); + map.insert(2, "zwei"); + map.insert(3, "drei"); - QCOMPARE(map.take(3), QLatin1String("drei")); - QVERIFY(!map.contains(3)); + QCOMPARE(map.take(3), QLatin1String("drei")); + QVERIFY(!map.contains(3)); + } + + { + QMultiMap<int, QString> multiMap; + QCOMPARE(multiMap.take(1), QString()); + QVERIFY(!multiMap.isDetached()); + + multiMap.insert(0, "value0"); + multiMap.insert(1, "value1"); + multiMap.insert(0, "value0_1"); + multiMap.insert(0, "value0_2"); + + // The most recently inserted value is returned + QCOMPARE(multiMap.take(0), u"value0_2"); + QCOMPARE(multiMap.take(0), u"value0_1"); + QCOMPARE(multiMap.take(0), u"value0"); + QCOMPARE(multiMap.take(0), QString()); + QVERIFY(!multiMap.contains(0)); + } } void tst_QMap::iterators() @@ -834,14 +1175,125 @@ void tst_QMap::iterators() } } +void tst_QMap::multimapIterators() +{ + QMultiMap<int, QString> map; + const QString testString = "Teststring %1-%2"; + + for (int i = 0; i < 5; ++i) { + // reverse order, because the last added is returned first. + for (int j = 4; j >= 0; --j) + map.insert(i, testString.arg(i).arg(j)); + } + + // STL-style iterators + auto stlIt = map.begin(); + QCOMPARE(stlIt.value(), u"Teststring 0-0"); + + stlIt++; + QCOMPARE(stlIt.value(), u"Teststring 0-1"); + + std::advance(stlIt, 10); + QCOMPARE(stlIt.value(), u"Teststring 2-1"); + + std::advance(stlIt, -4); + QCOMPARE(stlIt.value(), u"Teststring 1-2"); + + stlIt--; + QCOMPARE(stlIt.value(), u"Teststring 1-1"); + + // STL-style const iterators + auto cstlIt = map.cbegin(); + QCOMPARE(cstlIt.value(), u"Teststring 0-0"); + + cstlIt++; + QCOMPARE(cstlIt.value(), u"Teststring 0-1"); + + std::advance(cstlIt, 16); + QCOMPARE(cstlIt.value(), u"Teststring 3-2"); + + std::advance(cstlIt, -6); + QCOMPARE(cstlIt.value(), u"Teststring 2-1"); + + cstlIt--; + QCOMPARE(cstlIt.value(), u"Teststring 2-0"); + + // Java-style iterator + QMultiMapIterator javaIt(map); + int i = 0; + int j = 0; + while (javaIt.hasNext()) { + javaIt.next(); + QCOMPARE(javaIt.value(), testString.arg(i).arg(j)); + if (++j == 5) { + j = 0; + i++; + } + } + + i = 4; + j = 4; + while (javaIt.hasPrevious()) { + javaIt.previous(); + QCOMPARE(javaIt.value(), testString.arg(i).arg(j)); + if (--j < 0) { + j = 4; + i--; + } + } +} + +template <typename T> +void iteratorsInEmptyMapTestMethod() +{ + T map; + using ConstIter = typename T::const_iterator; + ConstIter it1 = map.cbegin(); + ConstIter it2 = map.constBegin(); + QVERIFY(it1 == it2 && it2 == ConstIter()); + QVERIFY(!map.isDetached()); + + ConstIter it3 = map.cend(); + ConstIter it4 = map.constEnd(); + QVERIFY(it3 == it4 && it4 == ConstIter()); + QVERIFY(!map.isDetached()); + + // to call const overloads of begin() and end() + const T map2; + ConstIter it5 = map2.begin(); + ConstIter it6 = map2.end(); + QVERIFY(it5 == it6 && it6 == ConstIter()); + QVERIFY(!map2.isDetached()); + + using Iter = typename T::iterator; + Iter it7 = map.begin(); + Iter it8 = map.end(); + QVERIFY(it7 == it8); +} + +void tst_QMap::iteratorsInEmptyMap() +{ + iteratorsInEmptyMapTestMethod<QMap<int, int>>(); + if (QTest::currentTestFailed()) + return; + + iteratorsInEmptyMapTestMethod<QMultiMap<int, int>>(); +} + void tst_QMap::keyIterator() { QMap<int, int> map; + using KeyIterator = QMap<int, int>::key_iterator; + KeyIterator it1 = map.keyBegin(); + KeyIterator it2 = map.keyEnd(); + QVERIFY(it1 == it2 && it2 == KeyIterator()); + QVERIFY(!map.isDetached()); + for (int i = 0; i < 100; ++i) map.insert(i, i*100); - QMap<int, int>::key_iterator key_it = map.keyBegin(); + KeyIterator key_it = map.keyBegin(); QMap<int, int>::const_iterator it = map.cbegin(); for (int i = 0; i < 100; ++i) { QCOMPARE(*key_it, it.key()); @@ -862,8 +1314,48 @@ void tst_QMap::keyIterator() QCOMPARE(std::count(map.keyBegin(), map.keyEnd(), 99), 1); // DefaultConstructible test - typedef QMap<int, int>::key_iterator keyIterator; - static_assert(std::is_default_constructible<keyIterator>::value); + static_assert(std::is_default_constructible<KeyIterator>::value); +} + +void tst_QMap::multimapKeyIterator() +{ + QMultiMap<int, int> map; + + using KeyIterator = QMultiMap<int, int>::key_iterator; + KeyIterator it1 = map.keyBegin(); + KeyIterator it2 = map.keyEnd(); + QVERIFY(it1 == it2 && it2 == KeyIterator()); + QVERIFY(!map.isDetached()); + + for (int i = 0; i < 5; ++i) { + for (int j = 4; j >= 0; --j) + map.insert(i, 100 * i + j); + } + + KeyIterator keyIt = map.keyBegin(); + QMultiMap<int, int>::const_iterator it = map.cbegin(); + for (int i = 0; i < 5; ++i) { + for (int j = 4; j >= 0; --j) { + QCOMPARE(*keyIt, it.key()); + ++keyIt; + ++it; + } + } + + keyIt = std::find(map.keyBegin(), map.keyEnd(), 3); + it = std::find(map.cbegin(), map.cend(), 3 * 100); + + QVERIFY(keyIt != map.keyEnd()); + QCOMPARE(*keyIt, it.key()); + QCOMPARE(*(keyIt++), (it++).key()); + QCOMPARE(*(keyIt--), (it--).key()); + QCOMPARE(*(++keyIt), (++it).key()); + QCOMPARE(*(--keyIt), (--it).key()); + + QCOMPARE(std::count(map.keyBegin(), map.keyEnd(), 2), 5); + + // DefaultConstructible test + static_assert(std::is_default_constructible<KeyIterator>::value); } void tst_QMap::keyValueIterator() @@ -925,27 +1417,168 @@ void tst_QMap::keyValueIterator() QCOMPARE(std::count(map.constKeyValueBegin(), map.constKeyValueEnd(), entry_type(key, value)), 1); } +void tst_QMap::multimapKeyValueIterator() +{ + QMultiMap<int, int> map; + using EntryType = QMultiMap<int, int>::const_key_value_iterator::value_type; + + for (int i = 0; i < 5; ++i) { + for (int j = 4; j >= 0; --j) + map.insert(i, 100 * i + j); + } + + auto keyValueIt = map.constKeyValueBegin(); + auto it = map.cbegin(); + + for (int i = 0; i < map.size(); ++i) { + QVERIFY(keyValueIt != map.constKeyValueEnd()); + QVERIFY(it != map.cend()); + + EntryType pair(it.key(), it.value()); + QCOMPARE(*keyValueIt, pair); + QCOMPARE(keyValueIt->first, pair.first); + QCOMPARE(keyValueIt->second, pair.second); + ++keyValueIt; + ++it; + } + + QVERIFY(keyValueIt == map.constKeyValueEnd()); + QVERIFY(it == map.cend()); + + int key = 3; + int value = 100 * 3; + keyValueIt = std::find(map.constKeyValueBegin(), map.constKeyValueEnd(), EntryType(key, value)); + it = std::find(map.cbegin(), map.cend(), value); + + QVERIFY(keyValueIt != map.constKeyValueEnd()); + QCOMPARE(*keyValueIt, EntryType(it.key(), it.value())); + + ++it; + ++keyValueIt; + QCOMPARE(*keyValueIt, EntryType(it.key(), it.value())); + + --it; + --keyValueIt; + QCOMPARE(*keyValueIt, EntryType(it.key(), it.value())); + + std::advance(it, 5); + std::advance(keyValueIt, 5); + QCOMPARE(*keyValueIt, EntryType(it.key(), it.value())); + + std::advance(it, -5); + std::advance(keyValueIt, -5); + QCOMPARE(*keyValueIt, EntryType(it.key(), it.value())); + + key = 2; + value = 100 * 2 + 2; + auto cnt = std::count(map.constKeyValueBegin(), map.constKeyValueEnd(), EntryType(key, value)); + QCOMPARE(cnt, 1); +} + +template <typename T> +void keyValueIteratorInEmptyMapTestMethod() +{ + T map; + using ConstKeyValueIter = typename T::const_key_value_iterator; + + ConstKeyValueIter it1 = map.constKeyValueBegin(); + ConstKeyValueIter it2 = map.constKeyValueEnd(); + QVERIFY(it1 == it2 && it2 == ConstKeyValueIter()); + QVERIFY(!map.isDetached()); + + const T map2; + ConstKeyValueIter it3 = map2.keyValueBegin(); + ConstKeyValueIter it4 = map2.keyValueEnd(); + QVERIFY(it3 == it4 && it4 == ConstKeyValueIter()); + QVERIFY(!map2.isDetached()); + + using KeyValueIter = typename T::key_value_iterator; + + KeyValueIter it5 = map.keyValueBegin(); + KeyValueIter it6 = map.keyValueEnd(); + QVERIFY(it5 == it6); +} + +void tst_QMap::keyValueIteratorInEmptyMap() +{ + keyValueIteratorInEmptyMapTestMethod<QMap<int, int>>(); + if (QTest::currentTestFailed()) + return; + + keyValueIteratorInEmptyMapTestMethod<QMultiMap<int, int>>(); +} + void tst_QMap::keys_values_uniqueKeys() { + { + QMap<QString, int> map; + QVERIFY(map.keys().isEmpty()); + QVERIFY(map.keys(1).isEmpty()); + QVERIFY(map.values().isEmpty()); + QVERIFY(!map.isDetached()); + + map.insert("one", 1); + QCOMPARE(map.keys(), QStringList({ "one" })); + QCOMPARE(map.keys(1), QStringList({ "one" })); + QCOMPARE(map.values(), QList<int>({ 1 })); + + map.insert("two", 2); + QCOMPARE(map.keys(), QStringList({ "one", "two" })); + QCOMPARE(map.keys(1), QStringList({ "one" })); + QCOMPARE(map.values(), QList<int>({ 1, 2 })); + + map.insert("three", 2); + QCOMPARE(map.keys(), QStringList({ "one", "three", "two" })); + QCOMPARE(map.keys(2), QStringList({ "three", "two" })); + QCOMPARE(map.values(), QList<int>({ 1, 2, 2 })); + + map.insert("one", 0); + QCOMPARE(map.keys(), QStringList({ "one", "three", "two" })); + QCOMPARE(map.keys(1), QStringList()); + QCOMPARE(map.keys(0), QStringList({ "one" })); + QCOMPARE(map.keys(2), QStringList({ "three", "two" })); + QCOMPARE(map.values(), QList<int>({ 0, 2, 2 })); + } + QMultiMap<QString, int> map; QVERIFY(map.keys().isEmpty()); + QVERIFY(map.keys(1).isEmpty()); + QVERIFY(map.uniqueKeys().isEmpty()); QVERIFY(map.values().isEmpty()); + QVERIFY(map.values("key").isEmpty()); + QVERIFY(!map.isDetached()); - map.insertMulti("alpha", 1); + map.insert("alpha", 1); QVERIFY(map.keys() == (QList<QString>() << "alpha")); QVERIFY(map.values() == (QList<int>() << 1)); + QVERIFY(map.uniqueKeys() == QList<QString>({ "alpha" })); - map.insertMulti("beta", -2); + map.insert("beta", -2); QVERIFY(map.keys() == (QList<QString>() << "alpha" << "beta")); QVERIFY(map.values() == (QList<int>() << 1 << -2)); + QVERIFY(map.uniqueKeys() == QList<QString>({ "alpha", "beta" })); - map.insertMulti("alpha", 2); + map.insert("alpha", 2); QVERIFY(map.keys() == (QList<QString>() << "alpha" << "alpha" << "beta")); QVERIFY(map.values() == (QList<int>() << 2 << 1 << -2)); + QVERIFY(map.uniqueKeys() == QList<QString>({ "alpha", "beta" })); + QVERIFY(map.values("alpha") == QList<int>({ 2, 1 })); - map.insertMulti("beta", 4); + map.insert("beta", 4); QVERIFY(map.keys() == (QList<QString>() << "alpha" << "alpha" << "beta" << "beta")); QVERIFY(map.values() == (QList<int>() << 2 << 1 << 4 << -2)); + QVERIFY(map.uniqueKeys() == QList<QString>({ "alpha", "beta" })); + QVERIFY(map.values("alpha") == QList<int>({ 2, 1 })); + QVERIFY(map.values("beta") == QList<int>({ 4, -2 })); + + map.insert("gamma", 2); + QVERIFY(map.keys() == QList<QString>({ "alpha", "alpha", "beta", "beta", "gamma" })); + QVERIFY(map.values() == QList<int>({ 2, 1, 4, -2, 2 })); + QVERIFY(map.uniqueKeys() == QList<QString>({ "alpha", "beta", "gamma" })); + QVERIFY(map.values("alpha") == QList<int>({ 2, 1 })); + QVERIFY(map.values("beta") == QList<int>({ 4, -2 })); + QVERIFY(map.values("gamma") == QList<int>({ 2 })); + QVERIFY(map.keys(2) == QList<QString>({ "alpha", "gamma" })); } void tst_QMap::qmultimap_specific() @@ -968,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); @@ -1046,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); @@ -1073,6 +1706,37 @@ void tst_QMap::const_shared_null() void tst_QMap::equal_range() { + { + const QMap<int, QString> constMap; + QCOMPARE(constMap.equal_range(1), qMakePair(constMap.constEnd(), constMap.constEnd())); + QVERIFY(!constMap.isDetached()); + + QMap<int, QString> map; + QCOMPARE(map.equal_range(1), qMakePair(map.end(), map.end())); + + map.insert(1, "value1"); + map.insert(5, "value5"); + map.insert(1, "value0"); + + auto pair = map.equal_range(1); + QCOMPARE(pair.first.value(), "value0"); + QCOMPARE(pair.second.value(), "value5"); + auto b = map.find(1); + auto e = map.find(5); + QCOMPARE(pair, qMakePair(b, e)); + + pair = map.equal_range(3); + QCOMPARE(pair.first.value(), "value5"); + QCOMPARE(pair.second.value(), "value5"); + QCOMPARE(pair, qMakePair(e, e)); + + QCOMPARE(map.equal_range(10), qMakePair(map.end(), map.end())); + } + + const QMultiMap<int, QString> constMap; + QCOMPARE(constMap.equal_range(1), qMakePair(constMap.constEnd(), constMap.constEnd())); + QVERIFY(!constMap.isDetached()); + QMultiMap<int, QString> map; const QMultiMap<int, QString> &cmap = map; @@ -1137,7 +1801,7 @@ void tst_QMap::equal_range() QCOMPARE(cresult.first, cmap.find(2)); QCOMPARE(cresult.second, cmap.find(4)); - map.insertMulti(1, "another one"); + map.insert(1, "another one"); result = map.equal_range(1); QCOMPARE(result.first, map.find(1)); @@ -1150,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) { @@ -1233,12 +1891,15 @@ void testDetachWhenInsert() dest.insert(3, 3); Map<int, int> destCopy = dest; - dest.insert(source); + if constexpr (std::is_same_v<decltype(dest), QMap<int, int>>) + dest.insert(source); // QMap + else + dest.unite(source); // QMultiMap QCOMPARE(source, referenceSource); QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } // copy insertion of shared map @@ -1253,13 +1914,16 @@ void testDetachWhenInsert() dest.insert(3, 3); Map<int, int> destCopy = dest; - dest.insert(source); + if constexpr (std::is_same_v<decltype(dest), QMap<int, int>>) + dest.insert(source); // QMap + else + dest.unite(source); // QMultiMap QCOMPARE(source, referenceSource); QCOMPARE(sourceCopy, referenceSource); QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } // move insertion of non-shared map @@ -1273,10 +1937,13 @@ void testDetachWhenInsert() dest.insert(3, 3); Map<int, int> destCopy = dest; - dest.insert(source); + if constexpr (std::is_same_v<decltype(dest), QMap<int, int>>) + dest.insert(source); // QMap + else + dest.unite(source); // QMultiMap QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } // move insertion of shared map @@ -1291,18 +1958,33 @@ void testDetachWhenInsert() dest.insert(3, 3); Map<int, int> destCopy = dest; - dest.insert(std::move(source)); + if constexpr (std::is_same_v<decltype(dest), QMap<int, int>>) + dest.insert(std::move(source)); // QMap + else + dest.unite(std::move(source)); // QMultiMap QCOMPARE(sourceCopy, referenceSource); QCOMPARE(dest, referenceDestination); - QCOMPARE(destCopy.count(), 1); // unchanged + QCOMPARE(destCopy.size(), 1); // unchanged } }; void tst_QMap::insertMap() { { + QMap<int, int> map1; + QMap<int, int> map2; + QVERIFY(map1.isEmpty()); + QVERIFY(map2.isEmpty()); + + map1.insert(map2); + QVERIFY(map1.isEmpty()); + QVERIFY(map2.isEmpty()); + QVERIFY(!map1.isDetached()); + QVERIFY(!map2.isDetached()); + } + { QMap<int, int> map; map.insert(1, 1); map.insert(2, 2); @@ -1315,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); } @@ -1330,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); @@ -1352,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); } { @@ -1361,8 +2043,12 @@ 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; + map3.insert(std::move(map2)); + QCOMPARE(map3, map); } { QMap<int, int> map; @@ -1373,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); } @@ -1391,7 +2077,7 @@ void tst_QMap::insertMap() map.insert(map2); - QCOMPARE(map.count(), 1); + QCOMPARE(map.size(), 1); } testDetachWhenInsert<QMap>(); @@ -1453,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")); @@ -1463,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()); @@ -1547,48 +2233,48 @@ void tst_QMap::testInsertMultiWithHint() { QMultiMap<int, int> map; - map.insertMulti(map.end(), 64, 65); + map.insert(map.end(), 64, 65); map.insert(128, 129); map.insert(256, 257); sanityCheckTree(map, __LINE__); - map.insertMulti(map.end(), 512, 513); - map.insertMulti(map.end(), 512, 513 * 2); + map.insert(map.end(), 512, 513); + map.insert(map.end(), 512, 513 * 2); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 5); - map.insertMulti(map.end(), 256, 258); // wrong hint + map.insert(map.end(), 256, 258); // wrong hint sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 6); - QMultiMap<int, int>::iterator i = map.insertMulti(map.constBegin(), 256, 259); // wrong hint + QMultiMap<int, int>::iterator i = map.insert(map.constBegin(), 256, 259); // wrong hint sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 7); - QMultiMap<int, int>::iterator j = map.insertMulti(map.constBegin(), 69, 66); + QMultiMap<int, int>::iterator j = map.insert(map.constBegin(), 69, 66); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 8); - j = map.insertMulti(j, 68, 259); + j = map.insert(j, 68, 259); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 9); - j = map.insertMulti(j, 67, 67); + j = map.insert(j, 67, 67); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 10); - i = map.insertMulti(i, 256, 259); + i = map.insert(i, 256, 259); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 11); - i = map.insertMulti(i, 256, 260); + i = map.insert(i, 256, 260); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 12); - map.insertMulti(i, 64, 67); + map.insert(i, 64, 67); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 13); - map.insertMulti(map.constBegin(), 20, 20); + map.insert(map.constBegin(), 20, 20); sanityCheckTree(map, __LINE__); QCOMPARE(map.size(), 14); } @@ -1597,9 +2283,9 @@ void tst_QMap::eraseValidIteratorOnSharedMap() { QMultiMap<int, int> a, b; a.insert(10, 10); - a.insertMulti(10, 40); - a.insertMulti(10, 25); - a.insertMulti(10, 30); + a.insert(10, 40); + a.insert(10, 25); + a.insert(10, 30); a.insert(20, 20); QMultiMap<int, int>::iterator i = a.begin(); @@ -1624,8 +2310,8 @@ void tst_QMap::eraseValidIteratorOnSharedMap() // Border cases QMultiMap <QString, QString> ms1, ms2, ms3; ms1.insert("foo", "bar"); - ms1.insertMulti("foo", "quux"); - ms1.insertMulti("foo", "bar"); + ms1.insert("foo", "quux"); + ms1.insert("foo", "bar"); QMultiMap <QString, QString>::iterator si = ms1.begin(); ms2 = ms1; @@ -1661,6 +2347,14 @@ void tst_QMap::removeElementsInMap() }; { + QMap<int, int> map; + QCOMPARE(map.remove(1), 0); + QVERIFY(!map.isDetached()); + + auto cnt = map.removeIf([](QMap<int, int>::iterator) { return true; }); + QCOMPARE(cnt, 0); + } + { QMap<SharedInt, int> map { { SharedInt(1), 1 }, { SharedInt(2), 2 }, @@ -1718,9 +2412,21 @@ void tst_QMap::removeElementsInMap() QCOMPARE(map.size(), 0); QCOMPARE(map2.size(), 4); + + auto cnt = map2.removeIf([](auto it) { return (*it % 2) == 0; }); + QCOMPARE(cnt, 2); + QCOMPARE(map2.size(), 2); } { + QMultiMap<int, int> map; + QCOMPARE(map.remove(1), 0); + QVERIFY(!map.isDetached()); + + auto cnt = map.removeIf([](QMultiMap<int, int>::iterator) { return true; }); + QCOMPARE(cnt, 0); + } + { QMultiMap<SharedInt, int> multimap { { SharedInt(1), 10 }, { SharedInt(1), 11 }, @@ -1817,8 +2523,127 @@ void tst_QMap::removeElementsInMap() QCOMPARE(multimap.size(), 0); QCOMPARE(multimap2.size(), 12); + + auto cnt = multimap2.removeIf([](auto it) { return (*it % 2) == 0; }); + QCOMPARE(cnt, 8); + QCOMPARE(multimap2.size(), 4); } } +template <typename QtMap, typename StdMap> +void toStdMapTestMethod(const StdMap &expectedMap) +{ + QtMap map; + QVERIFY(map.isEmpty()); + auto stdMap = map.toStdMap(); + QVERIFY(stdMap.empty()); + QVERIFY(!map.isDetached()); + + map.insert(1, "value1"); + map.insert(2, "value2"); + map.insert(3, "value3"); + map.insert(1, "value0"); + + stdMap = map.toStdMap(); + QCOMPARE(stdMap, expectedMap); +} + +void tst_QMap::toStdMap() +{ + const std::map<int, QString> expectedMap { {1, "value0"}, {2, "value2"}, {3, "value3"} }; + toStdMapTestMethod<QMap<int, QString>>(expectedMap); + if (QTest::currentTestFailed()) + return; + + const std::multimap<int, QString> expectedMultiMap { + {1, "value0"}, {1, "value1"}, {2, "value2"}, {3, "value3"} }; + 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() +{ + QMultiMap<int, QString> referenceMap; + referenceMap.insert(1, "value1"); + referenceMap.insert(2, "value2"); + referenceMap.insert(3, "value3"); + referenceMap.insert(1, "value1_2"); + referenceMap.insert(referenceMap.find(2), 2, "value2_2"); + referenceMap.insert(referenceMap.end(), 1, "value1_3"); + + QMultiMap<int, QString> deprecatedMap; +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + deprecatedMap.insertMulti(1, "value1"); + deprecatedMap.insertMulti(2, "value2"); + deprecatedMap.insertMulti(3, "value3"); + deprecatedMap.insertMulti(1, "value1_2"); + deprecatedMap.insertMulti(deprecatedMap.find(2), 2, "value2_2"); + deprecatedMap.insertMulti(deprecatedMap.end(), 1, "value1_3"); +QT_WARNING_POP + + QCOMPARE(deprecatedMap, referenceMap); +} + +void tst_QMap::deprecatedIteratorApis() +{ + QMap<int, QString> map; + QString testString = "Teststring %1"; + for (int i = 1; i < 100; ++i) + map.insert(i, testString.arg(i)); + + auto it = map.begin(); + QCOMPARE(it.value(), QLatin1String("Teststring 1")); + QT_IGNORE_DEPRECATIONS(it += 5;) + QCOMPARE(it.value(), QLatin1String("Teststring 6")); + QT_IGNORE_DEPRECATIONS(it = it - 3;) + QCOMPARE(it.value(), QLatin1String("Teststring 3")); + + auto cit = map.constBegin(); + QCOMPARE(cit.value(), QLatin1String("Teststring 1")); + QT_IGNORE_DEPRECATIONS(cit += 5;) + QCOMPARE(cit.value(), QLatin1String("Teststring 6")); + QT_IGNORE_DEPRECATIONS(cit = cit - 3;) + QCOMPARE(cit.value(), QLatin1String("Teststring 3")); +} + +void tst_QMap::deprecatedInsert() +{ + QMultiMap<int, QString> refMap; + refMap.insert(1, "value1"); + refMap.insert(2, "value2"); + refMap.insert(3, "value3"); + + QMultiMap<int, QString> depMap = refMap; + + QMultiMap<int, QString> otherMap; + otherMap.insert(1, "value1_2"); + otherMap.insert(3, "value3_2"); + otherMap.insert(4, "value4"); + + refMap.unite(otherMap); + QT_IGNORE_DEPRECATIONS(depMap.insert(otherMap);) + + QCOMPARE(refMap, depMap); +} +#endif // QT_DEPRECATED_SINCE(6, 0) + QTEST_APPLESS_MAIN(tst_QMap) #include "tst_qmap.moc" |