summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp')
-rw-r--r--tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp749
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"