aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp')
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
new file mode 100644
index 0000000000..b2908ac5bb
--- /dev/null
+++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 basysKom GmbH.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QQmlEngine>
+#include <private/qv4identifiertable_p.h>
+
+class tst_qv4identifiertable : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void sweepFirstEntryInBucket();
+ void sweepCenterEntryInBucket();
+ void sweepLastEntryInBucket();
+ void sweepFirstEntryInSameBucketWithDifferingHash();
+ void dontSweepAcrossBucketBoundaries();
+ void sweepAcrossBucketBoundariesIfFirstBucketFull();
+};
+
+void tst_qv4identifiertable::sweepFirstEntryInBucket()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // All strings go into the same bucket
+ entry1->stringHash = 0;
+ entry2->stringHash = 0;
+ entry3->stringHash = 0;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+
+ QCOMPARE(table.size, 3);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+ entry3->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry2);
+ QCOMPARE(table.entriesByHash[1], entry3);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+void tst_qv4identifiertable::sweepCenterEntryInBucket()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // All strings go into the same bucket
+ entry1->stringHash = 0;
+ entry2->stringHash = 0;
+ entry3->stringHash = 0;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+
+ QCOMPARE(table.size, 3);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+
+ entry1->setMarkBit();
+ // second entry not marked
+ entry3->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry3);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+void tst_qv4identifiertable::sweepLastEntryInBucket()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // All strings go into the same bucket
+ entry1->stringHash = 0;
+ entry2->stringHash = 0;
+ entry3->stringHash = 0;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+
+ QCOMPARE(table.size, 3);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+
+ entry1->setMarkBit();
+ entry2->setMarkBit();
+ // third entry not marked
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+void tst_qv4identifiertable::sweepFirstEntryInSameBucketWithDifferingHash()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+
+ // First and second entry have differing hash but end up in the
+ // same bucket after modulo alloc.
+ entry1->stringHash = 0;
+ entry2->stringHash = 5;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+
+ QCOMPARE(table.size, 2);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry2);
+ QCOMPARE(table.entriesByHash[1], nullptr);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+}
+
+void tst_qv4identifiertable::dontSweepAcrossBucketBoundaries()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/1);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+
+ // Different buckets for both entries.
+ entry1->stringHash = 0;
+ entry2->stringHash = 1;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+
+ QCOMPARE(table.size, 2);
+ QCOMPARE(table.alloc, 5);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], nullptr);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], nullptr);
+}
+
+void tst_qv4identifiertable::sweepAcrossBucketBoundariesIfFirstBucketFull()
+{
+ QV4::ExecutionEngine engine;
+ QV4::IdentifierTable table(&engine, /*numBits*/3);
+
+ auto entry1 = engine.newString(QStringLiteral("one"));
+ auto entry2 = engine.newString(QStringLiteral("two"));
+ auto entry3 = engine.newString(QStringLiteral("three"));
+ auto entry4 = engine.newString(QStringLiteral("four"));
+
+ entry1->createHashValue();
+ entry2->createHashValue();
+ entry3->createHashValue();
+ entry4->createHashValue();
+
+ // First, third and fourth entry have the same bucket (after modulo) and
+ // would typically end up in order [entry1, entry3, entry4, entry2]. However
+ // since null termination isn't guaranteed, an insertion order of
+ // entry1, entry2, entry3 and entry4 results in a
+ // table [entry1, entry2, entry3, entry4].
+ entry1->stringHash = 0;
+ entry2->stringHash = 1;
+ entry3->stringHash = 11;
+ entry4->stringHash = 11;
+
+ // trigger insertion
+ table.asPropertyKey(entry1);
+ table.asPropertyKey(entry2);
+ table.asPropertyKey(entry3);
+ table.asPropertyKey(entry4);
+
+ QCOMPARE(table.size, 4);
+ QCOMPARE(table.alloc, 11);
+
+ QCOMPARE(table.entriesByHash[0], entry1);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry3);
+ QCOMPARE(table.entriesByHash[3], entry4);
+ QCOMPARE(table.entriesByHash[4], nullptr);
+
+ // first entry not marked
+ entry2->setMarkBit();
+ entry3->setMarkBit();
+ entry4->setMarkBit();
+
+ table.sweep();
+
+ QCOMPARE(table.entriesByHash[0], entry3);
+ QCOMPARE(table.entriesByHash[1], entry2);
+ QCOMPARE(table.entriesByHash[2], entry4);
+ QCOMPARE(table.entriesByHash[3], nullptr);
+}
+
+QTEST_MAIN(tst_qv4identifiertable)
+
+#include "tst_qv4identifiertable.moc"