diff options
Diffstat (limited to 'tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp')
-rw-r--r-- | tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp b/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp new file mode 100644 index 0000000000..cc1d8baa8e --- /dev/null +++ b/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp @@ -0,0 +1,749 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtTest/qtest.h> +#include <QtTest/private/qcomparisontesthelper_p.h> +#include <QtCore/qcontainerinfo.h> +#include <QtCore/qmetacontainer.h> +#include <QtCore/QMap> +#include <QtCore/QHash> + +#include <QtCore/qvector.h> +#include <QtCore/qset.h> +#include <QtCore/qstring.h> +#include <QtCore/qbytearray.h> + +#include <vector> +#include <set> +#include <forward_list> +#include <unordered_map> + +namespace CheckContainerTraits +{ +struct NotAContainer {}; + +static_assert(QContainerInfo::has_size_v<QVector<int>>); +static_assert(QContainerInfo::has_size_v<QSet<int>>); +static_assert(!QContainerInfo::has_size_v<NotAContainer>); +static_assert(QContainerInfo::has_size_v<std::vector<int>>); +static_assert(QContainerInfo::has_size_v<std::set<int>>); +static_assert(!QContainerInfo::has_size_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_clear_v<QVector<int>>); +static_assert(QContainerInfo::has_clear_v<QSet<int>>); +static_assert(!QContainerInfo::has_clear_v<NotAContainer>); +static_assert(QContainerInfo::has_clear_v<std::vector<int>>); +static_assert(QContainerInfo::has_clear_v<std::set<int>>); +static_assert(QContainerInfo::has_clear_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_at_index_v<QVector<int>>); +static_assert(!QContainerInfo::has_at_index_v<QSet<int>>); +static_assert(!QContainerInfo::has_at_index_v<NotAContainer>); +static_assert(QContainerInfo::has_at_index_v<std::vector<int>>); +static_assert(!QContainerInfo::has_at_index_v<std::set<int>>); +static_assert(!QContainerInfo::has_at_index_v<std::forward_list<int>>); + +static_assert(QContainerInfo::can_get_at_index_v<QVector<int>>); +static_assert(!QContainerInfo::can_get_at_index_v<QSet<int>>); +static_assert(!QContainerInfo::can_get_at_index_v<NotAContainer>); +static_assert(QContainerInfo::can_get_at_index_v<std::vector<int>>); +static_assert(!QContainerInfo::can_get_at_index_v<std::set<int>>); +static_assert(!QContainerInfo::can_get_at_index_v<std::forward_list<int>>); + +static_assert(QContainerInfo::can_set_at_index_v<QVector<int>>); +static_assert(!QContainerInfo::can_set_at_index_v<QSet<int>>); +static_assert(!QContainerInfo::can_set_at_index_v<NotAContainer>); +static_assert(QContainerInfo::can_set_at_index_v<std::vector<int>>); +static_assert(!QContainerInfo::can_set_at_index_v<std::set<int>>); +static_assert(!QContainerInfo::can_set_at_index_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_push_back_v<QVector<int>>); +static_assert(!QContainerInfo::has_push_back_v<QSet<int>>); +static_assert(!QContainerInfo::has_push_back_v<NotAContainer>); +static_assert(QContainerInfo::has_push_back_v<std::vector<int>>); +static_assert(!QContainerInfo::has_push_back_v<std::set<int>>); +static_assert(!QContainerInfo::has_push_back_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_push_front_v<QVector<int>>); +static_assert(!QContainerInfo::has_push_front_v<QSet<int>>); +static_assert(!QContainerInfo::has_push_front_v<NotAContainer>); +static_assert(!QContainerInfo::has_push_front_v<std::vector<int>>); +static_assert(!QContainerInfo::has_push_front_v<std::set<int>>); +static_assert(QContainerInfo::has_push_front_v<std::forward_list<int>>); + +static_assert(!QContainerInfo::has_insert_v<QVector<int>>); +static_assert(QContainerInfo::has_insert_v<QSet<int>>); +static_assert(!QContainerInfo::has_insert_v<NotAContainer>); +static_assert(!QContainerInfo::has_insert_v<std::vector<int>>); +static_assert(QContainerInfo::has_insert_v<std::set<int>>); +static_assert(!QContainerInfo::has_insert_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_pop_back_v<QVector<int>>); +static_assert(!QContainerInfo::has_pop_back_v<QSet<int>>); +static_assert(!QContainerInfo::has_pop_back_v<NotAContainer>); +static_assert(QContainerInfo::has_pop_back_v<std::vector<int>>); +static_assert(!QContainerInfo::has_pop_back_v<std::set<int>>); +static_assert(!QContainerInfo::has_pop_back_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_pop_front_v<QVector<int>>); +static_assert(!QContainerInfo::has_pop_front_v<QSet<int>>); +static_assert(!QContainerInfo::has_pop_front_v<NotAContainer>); +static_assert(!QContainerInfo::has_pop_front_v<std::vector<int>>); +static_assert(!QContainerInfo::has_pop_front_v<std::set<int>>); +static_assert(QContainerInfo::has_pop_front_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_iterator_v<QVector<int>>); +static_assert(QContainerInfo::has_iterator_v<QSet<int>>); +static_assert(!QContainerInfo::has_iterator_v<NotAContainer>); +static_assert(QContainerInfo::has_iterator_v<std::vector<int>>); +static_assert(QContainerInfo::has_iterator_v<std::set<int>>); +static_assert(QContainerInfo::has_iterator_v<std::forward_list<int>>); + +static_assert(QContainerInfo::has_const_iterator_v<QVector<int>>); +static_assert(QContainerInfo::has_const_iterator_v<QSet<int>>); +static_assert(!QContainerInfo::has_const_iterator_v<NotAContainer>); +static_assert(QContainerInfo::has_const_iterator_v<std::vector<int>>); +static_assert(QContainerInfo::has_const_iterator_v<std::set<int>>); +static_assert(QContainerInfo::has_const_iterator_v<std::forward_list<int>>); + +static_assert(QContainerInfo::iterator_dereferences_to_value_v<QVector<int>>); +static_assert(QContainerInfo::iterator_dereferences_to_value_v<QSet<int>>); +static_assert(!QContainerInfo::iterator_dereferences_to_value_v<NotAContainer>); +static_assert(QContainerInfo::iterator_dereferences_to_value_v<std::vector<int>>); +static_assert(QContainerInfo::iterator_dereferences_to_value_v<std::set<int>>); +static_assert(QContainerInfo::iterator_dereferences_to_value_v<std::forward_list<int>>); + +static_assert(QContainerInfo::can_set_value_at_iterator_v<QVector<int>>); +static_assert(!QContainerInfo::can_set_value_at_iterator_v<QSet<int>>); +static_assert(!QContainerInfo::can_set_value_at_iterator_v<NotAContainer>); +static_assert(QContainerInfo::can_set_value_at_iterator_v<std::vector<int>>); +static_assert(!QContainerInfo::can_set_value_at_iterator_v<std::set<int>>); +static_assert(QContainerInfo::can_set_value_at_iterator_v<std::forward_list<int>>); + +static_assert(QContainerInfo::can_insert_value_at_iterator_v<QVector<int>>); +static_assert(QContainerInfo::can_insert_value_at_iterator_v<QSet<int>>); +static_assert(!QContainerInfo::can_insert_value_at_iterator_v<NotAContainer>); +static_assert(QContainerInfo::can_insert_value_at_iterator_v<std::vector<int>>); +static_assert(!QContainerInfo::can_insert_value_at_iterator_v<std::forward_list<int>>); + +// The iterator is only a hint, but syntactically indistinguishable from others. +// It's explicitly there to be signature compatible with std::vector::insert, though. +// Also, inserting into a set is not guaranteed to actually do anything. +static_assert(QContainerInfo::can_insert_value_at_iterator_v<std::set<int>>); + +static_assert(QContainerInfo::can_erase_at_iterator_v<QVector<int>>); +static_assert(QContainerInfo::can_erase_at_iterator_v<QSet<int>>); +static_assert(!QContainerInfo::can_erase_at_iterator_v<NotAContainer>); +static_assert(QContainerInfo::can_erase_at_iterator_v<std::vector<int>>); +static_assert(QContainerInfo::can_erase_at_iterator_v<std::set<int>>); +static_assert(!QContainerInfo::can_erase_at_iterator_v<std::forward_list<int>>); + +} + +class tst_QMetaContainer: public QObject +{ + Q_OBJECT + +private: + QVector<QMetaType> qvector; + std::vector<QString> stdvector; + QSet<QByteArray> qset; + std::set<int> stdset; + std::forward_list<QMetaSequence> forwardList; + + QHash<int, QMetaType> qhash; + QMap<QByteArray, bool> qmap; + std::map<QString, int> stdmap; + std::unordered_map<int, QMetaAssociation> stdunorderedmap; + +private slots: + void init(); + void compareCompiles(); + void testSequence_data(); + void testSequence(); + + void testAssociation_data(); + void testAssociation(); + + void cleanup(); +}; + +void tst_QMetaContainer::init() +{ + qvector = { QMetaType(), QMetaType::fromType<QString>(), QMetaType::fromType<int>() }; + stdvector = { QStringLiteral("foo"), QStringLiteral("bar"), QStringLiteral("baz") }; + qset = { "aaa", "bbb", "ccc" }; + stdset = { 1, 2, 3, 42, 45, 11 }; + forwardList = { + QMetaSequence::fromContainer<QVector<QMetaType>>(), + QMetaSequence::fromContainer<std::vector<QString>>(), + QMetaSequence::fromContainer<QSet<QByteArray>>(), + QMetaSequence::fromContainer<std::set<int>>(), + QMetaSequence::fromContainer<std::forward_list<QMetaSequence>>() + }; + qhash = { + { 233, QMetaType() }, + { 11, QMetaType::fromType<QByteArray>() }, + { 6626, QMetaType::fromType<bool>() } + }; + qmap = { + { "eins", true }, + { "zwei", false }, + { "elfundvierzig", true } + }; + + stdmap = { + { QStringLiteral("dkdkdkd"), 58583 }, + { QStringLiteral("ooo30393"), 12 }, + { QStringLiteral("2dddd30393"), 999999 }, + }; + stdunorderedmap = { + { 11, QMetaAssociation::fromContainer<QHash<int, QMetaType>>() }, + { 12, QMetaAssociation::fromContainer<QMap<QByteArray, bool>>() }, + { 393, QMetaAssociation::fromContainer<std::map<QString, int>>() }, + { 293, QMetaAssociation::fromContainer<std::unordered_map<int, QMetaAssociation>>() } + }; +} + +void tst_QMetaContainer::compareCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile<QMetaSequence>(); + QTestPrivate::testEqualityOperatorsCompile<QMetaAssociation>(); +} + +void tst_QMetaContainer::cleanup() +{ + qvector.clear(); + stdvector.clear(); + qset.clear(); + stdset.clear(); + forwardList.clear(); + qhash.clear(); + qmap.clear(); + stdmap.clear(); + stdunorderedmap.clear(); +} + +void tst_QMetaContainer::testSequence_data() +{ + QTest::addColumn<void *>("container"); + QTest::addColumn<QMetaSequence>("metaSequence"); + QTest::addColumn<QMetaType>("metaType"); + QTest::addColumn<bool>("hasSize"); + QTest::addColumn<bool>("isIndexed"); + QTest::addColumn<bool>("canRemove"); + QTest::addColumn<bool>("hasBidirectionalIterator"); + QTest::addColumn<bool>("hasRandomAccessIterator"); + QTest::addColumn<bool>("canInsertAtIterator"); + QTest::addColumn<bool>("canEraseAtIterator"); + QTest::addColumn<bool>("isSortable"); + + QTest::addRow("QVector") + << static_cast<void *>(&qvector) + << QMetaSequence::fromContainer<QVector<QMetaType>>() + << QMetaType::fromType<QMetaType>() + << true << true << true << true << true << true << true << true; + QTest::addRow("std::vector") + << static_cast<void *>(&stdvector) + << QMetaSequence::fromContainer<std::vector<QString>>() + << QMetaType::fromType<QString>() + << true << true << true << true << true << true << true << true; + QTest::addRow("QSet") + << static_cast<void *>(&qset) + << QMetaSequence::fromContainer<QSet<QByteArray>>() + << QMetaType::fromType<QByteArray>() + << true << false << false << false << false << true << true << false; + QTest::addRow("std::set") + << static_cast<void *>(&stdset) + << QMetaSequence::fromContainer<std::set<int>>() + << QMetaType::fromType<int>() + << true << false << false << true << false << true << true << false; + QTest::addRow("std::forward_list") + << static_cast<void *>(&forwardList) + << QMetaSequence::fromContainer<std::forward_list<QMetaSequence>>() + << QMetaType::fromType<QMetaSequence>() + << false << false << true << false << false << false << false << true; +} + +void tst_QMetaContainer::testSequence() +{ + QFETCH(void *, container); + QFETCH(QMetaSequence, metaSequence); + QFETCH(QMetaType, metaType); + QFETCH(bool, hasSize); + QFETCH(bool, isIndexed); + QFETCH(bool, canRemove); + QFETCH(bool, hasBidirectionalIterator); + QFETCH(bool, hasRandomAccessIterator); + QFETCH(bool, canInsertAtIterator); + QFETCH(bool, canEraseAtIterator); + QFETCH(bool, isSortable); + + QVERIFY(metaSequence.canAddValue()); + QCOMPARE(metaSequence.hasSize(), hasSize); + QCOMPARE(metaSequence.canGetValueAtIndex(), isIndexed); + QCOMPARE(metaSequence.canSetValueAtIndex(), isIndexed); + QCOMPARE(metaSequence.canRemoveValue(), canRemove); + QCOMPARE(metaSequence.hasBidirectionalIterator(), hasBidirectionalIterator); + QCOMPARE(metaSequence.hasRandomAccessIterator(), hasRandomAccessIterator); + QCOMPARE(metaSequence.canInsertValueAtIterator(), canInsertAtIterator); + QCOMPARE(metaSequence.canEraseValueAtIterator(), canEraseAtIterator); + QCOMPARE(metaSequence.isSortable(), isSortable); + + QVariant var1(metaType); + QVariant var2(metaType); + QVariant var3(metaType); + + if (hasSize) { + const qsizetype size = metaSequence.size(container); + + // var1 is invalid, and our sets do not contain an invalid value so far. + metaSequence.addValue(container, var1.constData()); + QCOMPARE(metaSequence.size(container), size + 1); + if (canRemove) { + metaSequence.removeValue(container); + QCOMPARE(metaSequence.size(container), size); + } + } else { + metaSequence.addValue(container, var1.constData()); + if (canRemove) + metaSequence.removeValue(container); + } + + if (isIndexed) { + QVERIFY(hasSize); + const qsizetype size = metaSequence.size(container); + for (qsizetype i = 0; i < size; ++i) { + metaSequence.valueAtIndex(container, i, var1.data()); + metaSequence.valueAtIndex(container, size - i - 1, var2.data()); + + metaSequence.setValueAtIndex(container, i, var2.constData()); + metaSequence.setValueAtIndex(container, size - i - 1, var1.constData()); + + metaSequence.valueAtIndex(container, i, var3.data()); + QCOMPARE(var3, var2); + + metaSequence.valueAtIndex(container, size - i - 1, var3.data()); + QCOMPARE(var3, var1); + } + } + + QVERIFY(metaSequence.hasIterator()); + QVERIFY(metaSequence.hasConstIterator()); + QVERIFY(metaSequence.canGetValueAtIterator()); + QVERIFY(metaSequence.canGetValueAtConstIterator()); + + void *it = metaSequence.begin(container); + void *end = metaSequence.end(container); + QVERIFY(it); + QVERIFY(end); + + void *constIt = metaSequence.constBegin(container); + void *constEnd = metaSequence.constEnd(container); + QVERIFY(constIt); + QVERIFY(constEnd); + + const qsizetype size = metaSequence.diffIterator(end, it); + QCOMPARE(size, metaSequence.diffConstIterator(constEnd, constIt)); + if (hasSize) + QCOMPARE(size, metaSequence.size(container)); + + qsizetype count = 0; + for (; !metaSequence.compareIterator(it, end); + metaSequence.advanceIterator(it, 1), metaSequence.advanceConstIterator(constIt, 1)) { + metaSequence.valueAtIterator(it, var1.data()); + if (isIndexed) { + metaSequence.valueAtIndex(container, count, var2.data()); + QCOMPARE(var1, var2); + } + metaSequence.valueAtConstIterator(constIt, var3.data()); + QCOMPARE(var3, var1); + ++count; + } + + QCOMPARE(count, size); + QVERIFY(metaSequence.compareConstIterator(constIt, constEnd)); + + metaSequence.destroyIterator(it); + metaSequence.destroyIterator(end); + metaSequence.destroyConstIterator(constIt); + metaSequence.destroyConstIterator(constEnd); + + if (metaSequence.canSetValueAtIterator()) { + void *it = metaSequence.begin(container); + void *end = metaSequence.end(container); + QVERIFY(it); + QVERIFY(end); + + for (; !metaSequence.compareIterator(it, end); metaSequence.advanceIterator(it, 1)) { + metaSequence.valueAtIterator(it, var1.data()); + metaSequence.setValueAtIterator(it, var2.constData()); + metaSequence.valueAtIterator(it, var3.data()); + QCOMPARE(var2, var3); + var2 = var1; + } + + metaSequence.destroyIterator(it); + metaSequence.destroyIterator(end); + } + + if (metaSequence.hasBidirectionalIterator()) { + void *it = metaSequence.end(container); + void *end = metaSequence.begin(container); + QVERIFY(it); + QVERIFY(end); + + void *constIt = metaSequence.constEnd(container); + void *constEnd = metaSequence.constBegin(container); + QVERIFY(constIt); + QVERIFY(constEnd); + + qsizetype size = 0; + if (metaSequence.hasRandomAccessIterator()) { + size = metaSequence.diffIterator(end, it); + QCOMPARE(size, metaSequence.diffConstIterator(constEnd, constIt)); + } else { + size = -metaSequence.diffIterator(it, end); + } + + if (hasSize) + QCOMPARE(size, -metaSequence.size(container)); + + qsizetype count = 0; + do { + metaSequence.advanceIterator(it, -1); + metaSequence.advanceConstIterator(constIt, -1); + --count; + + metaSequence.valueAtIterator(it, var1.data()); + if (isIndexed) { + metaSequence.valueAtIndex(container, count - size, var2.data()); + QCOMPARE(var1, var2); + } + metaSequence.valueAtConstIterator(constIt, var3.data()); + QCOMPARE(var3, var1); + } while (!metaSequence.compareIterator(it, end)); + + QCOMPARE(count, size); + QVERIFY(metaSequence.compareConstIterator(constIt, constEnd)); + + metaSequence.destroyIterator(it); + metaSequence.destroyIterator(end); + metaSequence.destroyConstIterator(constIt); + metaSequence.destroyConstIterator(constEnd); + } + + if (canInsertAtIterator) { + void *it = metaSequence.begin(container); + void *end = metaSequence.end(container); + + const qsizetype size = metaSequence.diffIterator(end, it); + metaSequence.destroyIterator(end); + + metaSequence.insertValueAtIterator(container, it, var1.constData()); + metaSequence.destroyIterator(it); + it = metaSequence.begin(container); + metaSequence.insertValueAtIterator(container, it, var2.constData()); + metaSequence.destroyIterator(it); + it = metaSequence.begin(container); + metaSequence.insertValueAtIterator(container, it, var3.constData()); + + metaSequence.destroyIterator(it); + + it = metaSequence.begin(container); + end = metaSequence.end(container); + + const qsizetype newSize = metaSequence.diffIterator(end, it); + + if (metaSequence.isSortable()) { + QCOMPARE(newSize, size + 3); + QVariant var4(metaType); + metaSequence.valueAtIterator(it, var4.data()); + QCOMPARE(var4, var3); + metaSequence.advanceIterator(it, 1); + metaSequence.valueAtIterator(it, var4.data()); + QCOMPARE(var4, var2); + metaSequence.advanceIterator(it, 1); + metaSequence.valueAtIterator(it, var4.data()); + QCOMPARE(var4, var1); + } else { + QVERIFY(newSize >= size); + } + + if (canEraseAtIterator) { + for (int i = 0; i < newSize; ++i) { + metaSequence.destroyIterator(it); + it = metaSequence.begin(container); + metaSequence.eraseValueAtIterator(container, it); + } + + metaSequence.destroyIterator(it); + it = metaSequence.begin(container); + metaSequence.destroyIterator(end); + end = metaSequence.end(container); + QVERIFY(metaSequence.compareIterator(it, end)); + + metaSequence.addValue(container, var1.constData()); + metaSequence.addValue(container, var2.constData()); + metaSequence.addValue(container, var3.constData()); + } + + metaSequence.destroyIterator(end); + metaSequence.destroyIterator(it); + } + + QVERIFY(metaSequence.canClear()); + constIt = metaSequence.constBegin(container); + constEnd = metaSequence.constEnd(container); + QVERIFY(!metaSequence.compareConstIterator(constIt, constEnd)); + metaSequence.destroyConstIterator(constIt); + metaSequence.destroyConstIterator(constEnd); + + metaSequence.clear(container); + constIt = metaSequence.constBegin(container); + constEnd = metaSequence.constEnd(container); + QVERIFY(metaSequence.compareConstIterator(constIt, constEnd)); + metaSequence.destroyConstIterator(constIt); + metaSequence.destroyConstIterator(constEnd); + + QVERIFY(metaSequence.iface() != nullptr); + QMetaSequence defaultConstructed; + QVERIFY(defaultConstructed.iface() == nullptr); + QT_TEST_EQUALITY_OPS(QMetaSequence(), defaultConstructed, true); + QT_TEST_EQUALITY_OPS(QMetaSequence(), QMetaSequence(), true); + QT_TEST_EQUALITY_OPS(defaultConstructed, metaSequence, false); +} + +void tst_QMetaContainer::testAssociation_data() +{ + QTest::addColumn<void *>("container"); + QTest::addColumn<QMetaAssociation>("metaAssociation"); + QTest::addColumn<QMetaType>("keyType"); + QTest::addColumn<QMetaType>("mappedType"); + QTest::addColumn<bool>("hasSize"); + QTest::addColumn<bool>("canRemove"); + QTest::addColumn<bool>("canSetMapped"); + QTest::addColumn<bool>("hasBidirectionalIterator"); + QTest::addColumn<bool>("hasRandomAccessIterator"); + + QTest::addRow("QHash") + << static_cast<void *>(&qhash) + << QMetaAssociation::fromContainer<QHash<int, QMetaType>>() + << QMetaType::fromType<int>() + << QMetaType::fromType<QMetaType>() + << true << true << true << false << false; + QTest::addRow("QMap") + << static_cast<void *>(&qmap) + << QMetaAssociation::fromContainer<QMap<QByteArray, bool>>() + << QMetaType::fromType<QByteArray>() + << QMetaType::fromType<bool>() + << true << true << true << true << false; + QTest::addRow("std::map") + << static_cast<void *>(&stdmap) + << QMetaAssociation::fromContainer<std::map<QString, int>>() + << QMetaType::fromType<QString>() + << QMetaType::fromType<int>() + << true << true << true << true << false; + QTest::addRow("std::unorderedmap") + << static_cast<void *>(&stdunorderedmap) + << QMetaAssociation::fromContainer<std::unordered_map<int, QMetaAssociation>>() + << QMetaType::fromType<int>() + << QMetaType::fromType<QMetaAssociation>() + << true << true << true << false << false; + QTest::addRow("QSet") + << static_cast<void *>(&qset) + << QMetaAssociation::fromContainer<QSet<QByteArray>>() + << QMetaType::fromType<QByteArray>() + << QMetaType() + << true << true << false << false << false; + QTest::addRow("std::set") + << static_cast<void *>(&stdset) + << QMetaAssociation::fromContainer<std::set<int>>() + << QMetaType::fromType<int>() + << QMetaType() + << true << true << false << true << false; +} + +void tst_QMetaContainer::testAssociation() +{ + QFETCH(void *, container); + QFETCH(QMetaAssociation, metaAssociation); + QFETCH(QMetaType, keyType); + QFETCH(QMetaType, mappedType); + QFETCH(bool, hasSize); + QFETCH(bool, canRemove); + QFETCH(bool, canSetMapped); + QFETCH(bool, hasBidirectionalIterator); + QFETCH(bool, hasRandomAccessIterator); + + QCOMPARE(metaAssociation.hasSize(), hasSize); + QCOMPARE(metaAssociation.canRemoveKey(), canRemove); + QCOMPARE(metaAssociation.canSetMappedAtKey(), canSetMapped); + QCOMPARE(metaAssociation.canSetMappedAtIterator(), canSetMapped); + + // Apparently implementations can choose to provide "better" iterators than required by the std. + if (hasBidirectionalIterator) + QCOMPARE(metaAssociation.hasBidirectionalIterator(), hasBidirectionalIterator); + if (hasRandomAccessIterator) + QCOMPARE(metaAssociation.hasRandomAccessIterator(), hasRandomAccessIterator); + + QVariant key1(keyType); + QVariant key2(keyType); + QVariant key3(keyType); + + QVariant mapped1(mappedType); + QVariant mapped2(mappedType); + QVariant mapped3(mappedType); + + if (hasSize) { + const qsizetype size = metaAssociation.size(container); + + QVERIFY(metaAssociation.canInsertKey()); + + // var1 is invalid, and our containers do not contain an invalid key so far. + metaAssociation.insertKey(container, key1.constData()); + QCOMPARE(metaAssociation.size(container), size + 1); + metaAssociation.removeKey(container, key1.constData()); + QCOMPARE(metaAssociation.size(container), size); + } else { + metaAssociation.insertKey(container, key1.constData()); + metaAssociation.removeKey(container, key1.constData()); + } + + QVERIFY(metaAssociation.hasIterator()); + QVERIFY(metaAssociation.hasConstIterator()); + QVERIFY(metaAssociation.canGetKeyAtIterator()); + QVERIFY(metaAssociation.canGetKeyAtConstIterator()); + + void *it = metaAssociation.begin(container); + void *end = metaAssociation.end(container); + QVERIFY(it); + QVERIFY(end); + + void *constIt = metaAssociation.constBegin(container); + void *constEnd = metaAssociation.constEnd(container); + QVERIFY(constIt); + QVERIFY(constEnd); + + const qsizetype size = metaAssociation.diffIterator(end, it); + QCOMPARE(size, metaAssociation.diffConstIterator(constEnd, constIt)); + if (hasSize) + QCOMPARE(size, metaAssociation.size(container)); + + qsizetype count = 0; + for (; !metaAssociation.compareIterator(it, end); + metaAssociation.advanceIterator(it, 1), metaAssociation.advanceConstIterator(constIt, 1)) { + metaAssociation.keyAtIterator(it, key1.data()); + metaAssociation.keyAtConstIterator(constIt, key3.data()); + QCOMPARE(key3, key1); + ++count; + } + + QCOMPARE(count, size); + QVERIFY(metaAssociation.compareConstIterator(constIt, constEnd)); + + metaAssociation.destroyIterator(it); + metaAssociation.destroyIterator(end); + metaAssociation.destroyConstIterator(constIt); + metaAssociation.destroyConstIterator(constEnd); + + if (metaAssociation.canSetMappedAtIterator()) { + void *it = metaAssociation.begin(container); + void *end = metaAssociation.end(container); + QVERIFY(it); + QVERIFY(end); + + for (; !metaAssociation.compareIterator(it, end); metaAssociation.advanceIterator(it, 1)) { + metaAssociation.mappedAtIterator(it, mapped1.data()); + metaAssociation.setMappedAtIterator(it, mapped2.constData()); + metaAssociation.mappedAtIterator(it, mapped3.data()); + QCOMPARE(mapped2, mapped3); + mapped2 = mapped1; + } + + metaAssociation.destroyIterator(it); + metaAssociation.destroyIterator(end); + + it = metaAssociation.constBegin(container); + end = metaAssociation.constEnd(container); + QVERIFY(it); + QVERIFY(end); + + for (; !metaAssociation.compareConstIterator(it, end); metaAssociation.advanceConstIterator(it, 1)) { + metaAssociation.mappedAtConstIterator(it, mapped1.data()); + metaAssociation.keyAtConstIterator(it, key1.data()); + metaAssociation.setMappedAtKey(container, key1.constData(), mapped2.constData()); + metaAssociation.mappedAtConstIterator(it, mapped3.data()); + QCOMPARE(mapped2, mapped3); + mapped2 = mapped1; + } + + metaAssociation.destroyConstIterator(it); + metaAssociation.destroyConstIterator(end); + } + + if (metaAssociation.hasBidirectionalIterator()) { + void *it = metaAssociation.end(container); + void *end = metaAssociation.begin(container); + QVERIFY(it); + QVERIFY(end); + + void *constIt = metaAssociation.constEnd(container); + void *constEnd = metaAssociation.constBegin(container); + QVERIFY(constIt); + QVERIFY(constEnd); + + qsizetype size = 0; + if (metaAssociation.hasRandomAccessIterator()) { + size = metaAssociation.diffIterator(end, it); + QCOMPARE(size, metaAssociation.diffConstIterator(constEnd, constIt)); + } else { + size = -metaAssociation.diffIterator(it, end); + } + + if (hasSize) + QCOMPARE(size, -metaAssociation.size(container)); + + qsizetype count = 0; + do { + metaAssociation.advanceIterator(it, -1); + metaAssociation.advanceConstIterator(constIt, -1); + --count; + + metaAssociation.keyAtIterator(it, key1.data()); + metaAssociation.keyAtConstIterator(constIt, key3.data()); + QCOMPARE(key3, key1); + } while (!metaAssociation.compareIterator(it, end)); + + QCOMPARE(count, size); + QVERIFY(metaAssociation.compareConstIterator(constIt, constEnd)); + + metaAssociation.destroyIterator(it); + metaAssociation.destroyIterator(end); + metaAssociation.destroyConstIterator(constIt); + metaAssociation.destroyConstIterator(constEnd); + } + + QVERIFY(metaAssociation.canClear()); + constIt = metaAssociation.constBegin(container); + constEnd = metaAssociation.constEnd(container); + QVERIFY(!metaAssociation.compareConstIterator(constIt, constEnd)); + metaAssociation.destroyConstIterator(constIt); + metaAssociation.destroyConstIterator(constEnd); + + metaAssociation.clear(container); + constIt = metaAssociation.constBegin(container); + constEnd = metaAssociation.constEnd(container); + QVERIFY(metaAssociation.compareConstIterator(constIt, constEnd)); + metaAssociation.destroyConstIterator(constIt); + metaAssociation.destroyConstIterator(constEnd); + + QVERIFY(metaAssociation.iface() != nullptr); + QMetaAssociation defaultConstructed; + QVERIFY(defaultConstructed.iface() == nullptr); + QT_TEST_EQUALITY_OPS(QMetaAssociation(), QMetaAssociation(), true); + QT_TEST_EQUALITY_OPS(QMetaAssociation(), metaAssociation, false); +} + +QTEST_MAIN(tst_QMetaContainer) +#include "tst_qmetacontainer.moc" |