aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-07-12 16:08:17 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-07-19 10:52:31 +0200
commitef057772c41e84e9813f0ed113fc55224013404c (patch)
tree80d1a7247825bcfccb577ce2ab6c0f248d435439 /tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
parentb335d8311f7c0be9261305d5b41bbcbf94cd3d27 (diff)
Fix array-like methods on V4 sequences
We need to properly convert value type lists on assignment and we need to add the "length" property to the own properties. Furthermore, the V4 sequence methods were confused about integer type ranges. We teach them about qsizetype, properly range check everything, and drop the artificial limitation to INT_MAX. Pick-to: 6.4 Task-number: QTBUG-82443 Change-Id: Ie5af1130c9e78e412c171e6fa26a28a6a7a5d498 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp')
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index ebc677c74f..8bed8a9880 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -11,6 +11,7 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <QtCore/qscopeguard.h>
+#include <QtCore/qrandom.h>
#include <QtGui/qevent.h>
#include <QSignalSpy>
#include <QFont>
@@ -388,6 +389,9 @@ private slots:
void leakingAttributesQmlForeign();
void attachedOwnProperties();
void bindableOnly();
+ void v4SequenceMethods();
+ void v4SequenceMethodsWithParams_data();
+ void v4SequenceMethodsWithParams();
private:
QQmlEngine engine;
@@ -7410,6 +7414,165 @@ void tst_qqmllanguage::bindableOnly()
QCOMPARE(o->property("a").toInt(), 5);
}
+static void listsEqual(QObject *object, const char *method)
+{
+ const QByteArray v4SequencePropertyName = QByteArray("v4Sequence") + method;
+ const QByteArray jsArrayPropertyName = QByteArray("jsArray") + method;
+
+ const QList<QRectF> v4SequenceProperty
+ = object->property(v4SequencePropertyName.constData()).value<QList<QRectF>>();
+ const QList<QRectF> jsArrayProperty
+ = object->property(jsArrayPropertyName.constData()).value<QList<QRectF>>();
+
+ const qsizetype v4SequenceCount = v4SequenceProperty.count();
+ QCOMPARE(v4SequenceCount, jsArrayProperty.count());
+
+ for (qsizetype i = 0; i < v4SequenceCount; ++i)
+ QCOMPARE(v4SequenceProperty.at(i), jsArrayProperty.at(i));
+}
+
+void tst_qqmllanguage::v4SequenceMethods()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("v4SequenceMethods.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("v4SequenceToString"), object->property("jsArrayToString"));
+ QCOMPARE(object->property("v4SequenceToLocaleString"), object->property("jsArrayToLocaleString"));
+
+ QVERIFY(object->property("entriesMatch").toBool());
+ QVERIFY(object->property("keysMatch").toBool());
+ QVERIFY(object->property("valuesMatch").toBool());
+
+ listsEqual(object.data(), "Concat");
+ listsEqual(object.data(), "Pop");
+ listsEqual(object.data(), "Push");
+ listsEqual(object.data(), "Reverse");
+ listsEqual(object.data(), "Shift");
+ listsEqual(object.data(), "Unshift");
+ listsEqual(object.data(), "Filter");
+ listsEqual(object.data(), "Sort1");
+ listsEqual(object.data(), "Sort2");
+
+ QCOMPARE(object->property("v4SequenceFind"), object->property("jsArrayFind"));
+ QCOMPARE(object->property("v4SequenceFind").value<QRectF>().x(), 1.0);
+
+ QCOMPARE(object->property("v4SequenceFindIndex"), object->property("jsArrayFindIndex"));
+ QCOMPARE(object->property("v4SequenceFindIndex").toInt(), 1);
+
+ QCOMPARE(object->property("v4SequenceIncludes"), object->property("jsArrayIncludes"));
+ QVERIFY(object->property("v4SequenceIncludes").toBool());
+
+ QCOMPARE(object->property("v4SequenceJoin"), object->property("jsArrayJoin"));
+ QVERIFY(object->property("v4SequenceJoin").toString().contains(QStringLiteral("1")));
+
+ QCOMPARE(object->property("v4SequencePopped"), object->property("jsArrayPopped"));
+ QVERIFY(object->property("v4SequencePopped").value<QRectF>().x() != 1.0);
+
+ QCOMPARE(object->property("v4SequencePushed"), object->property("jsArrayPushed"));
+ QCOMPARE(object->property("v4SequencePushed").toInt(), 4);
+
+ QCOMPARE(object->property("v4SequenceShifted"), object->property("jsArrayShifted"));
+ QCOMPARE(object->property("v4SequenceShifted").value<QRectF>().x(), 1.0);
+
+ QCOMPARE(object->property("v4SequenceUnshifted"), object->property("jsArrayUnshifted"));
+ QCOMPARE(object->property("v4SequenceUnshifted").toInt(), 4);
+
+ QCOMPARE(object->property("v4SequenceIndexOf"), object->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("v4SequenceIndexOf").toInt(), 1);
+
+ QCOMPARE(object->property("v4SequenceLastIndexOf"), object->property("jsArrayLastIndexOf"));
+ QCOMPARE(object->property("v4SequenceLastIndexOf").toInt(), 2);
+
+ QCOMPARE(object->property("v4SequenceEvery"), object->property("jsArrayEvery"));
+ QVERIFY(object->property("v4SequenceEvery").toBool());
+
+ QCOMPARE(object->property("v4SequenceSome"), object->property("jsArrayEvery"));
+ QVERIFY(object->property("v4SequenceSome").toBool());
+
+ QCOMPARE(object->property("v4SequenceForEach"), object->property("jsArrayForEach"));
+ QCOMPARE(object->property("v4SequenceForEach").toString(), QStringLiteral("-1--5--9-"));
+
+ QCOMPARE(object->property("v4SequenceMap").toStringList(), object->property("jsArrayMap").toStringList());
+ QCOMPARE(object->property("v4SequenceReduce").toString(), object->property("jsArrayReduce").toString());
+
+ QCOMPARE(object->property("v4SequenceOwnPropertyNames").toStringList(),
+ object->property("jsArrayOwnPropertyNames").toStringList());
+}
+
+void tst_qqmllanguage::v4SequenceMethodsWithParams_data()
+{
+ QTest::addColumn<double>("i");
+ QTest::addColumn<double>("j");
+ QTest::addColumn<double>("k");
+
+ const double indices[] = {
+ double(std::numeric_limits<qsizetype>::min()),
+ double(std::numeric_limits<qsizetype>::min()) + 1,
+ double(std::numeric_limits<uint>::min()) - 1,
+ double(std::numeric_limits<uint>::min()),
+ double(std::numeric_limits<uint>::min()) + 1,
+ double(std::numeric_limits<int>::min()),
+ -10, -3, -2, -1, 0, 1, 2, 3, 10,
+ double(std::numeric_limits<int>::max()),
+ double(std::numeric_limits<uint>::max()) - 1,
+ double(std::numeric_limits<uint>::max()),
+ double(std::numeric_limits<uint>::max()) + 1,
+ double(std::numeric_limits<qsizetype>::max() - 1),
+ double(std::numeric_limits<qsizetype>::max()),
+ };
+
+ // We cannot test the full cross product. So, take a random sample instead.
+ const qsizetype numIndices = sizeof(indices) / sizeof(double);
+ qsizetype seed = QRandomGenerator::global()->generate();
+ const int numSamples = 4;
+ for (int i = 0; i < numSamples; ++i) {
+ seed = qHash(i, seed);
+ const double vi = indices[qAbs(seed) % numIndices];
+ for (int j = 0; j < numSamples; ++j) {
+ seed = qHash(j, seed);
+ const double vj = indices[qAbs(seed) % numIndices];
+ for (int k = 0; k < numSamples; ++k) {
+ seed = qHash(k, seed);
+ const double vk = indices[qAbs(seed) % numIndices];
+ const QString tag = QLatin1String("%1/%2/%3")
+ .arg(QString::number(vi), QString::number(vj), QString::number(vk));
+ QTest::newRow(qPrintable(tag)) << vi << vj << vk;
+
+ // output all the tags so that we can find out what combination caused a test to hang.
+ qDebug().noquote() << "scheduling" << tag;
+ }
+ }
+ }
+}
+
+void tst_qqmllanguage::v4SequenceMethodsWithParams()
+{
+ QFETCH(double, i);
+ QFETCH(double, j);
+ QFETCH(double, k);
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("v4SequenceMethodsWithParams.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.createWithInitialProperties({
+ {QStringLiteral("i"), i},
+ {QStringLiteral("j"), j},
+ {QStringLiteral("k"), k}
+ }));
+ QVERIFY(!object.isNull());
+
+ listsEqual(object.data(), "CopyWithin");
+ listsEqual(object.data(), "Fill");
+ listsEqual(object.data(), "Slice");
+ listsEqual(object.data(), "Splice");
+ listsEqual(object.data(), "Spliced");
+
+ QCOMPARE(object->property("v4SequenceIndexOf"), object->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("v4SequenceLastIndexOf"), object->property("jsArrayLastIndexOf"));
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"