diff options
Diffstat (limited to 'tests/auto/qml')
19 files changed, 252 insertions, 475 deletions
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 6892680d79..4d1644f6b3 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -32,7 +32,6 @@ PRIVATETESTS += \ qqmlecmascript \ qqmlcontext \ qqmlexpression \ - qqmlimageprovider \ qqmlinstruction \ qqmllanguage \ qqmlproperty \ diff --git a/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml b/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml index 122c6a87c8..989b295cb5 100644 --- a/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml +++ b/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml @@ -37,7 +37,7 @@ Item{ root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3, "innerRect.border.width": 20}); root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root}); - root.bindingTestObject = c.createObject(root, {'testValue': (function(){return width * 3}) }) // use root.width - root.bindingThisTestObject = c.createObject(root, {'testValue': (function(){return this.width * 3}) }) // use width of Item within 'c' + root.bindingTestObject = c.createObject(root, {'testValue': Qt.binding(function(){return width * 3}) }) // use root.width + root.bindingThisTestObject = c.createObject(root, {'testValue': Qt.binding(function(){return this.width * 3}) }) // use width of Item within 'c' } } diff --git a/tests/auto/qml/qqmlecmascript/data/functionAssignment.1.qml b/tests/auto/qml/qqmlecmascript/data/functionAssignment.1.qml index 09540f1f6e..0b1b45b41b 100644 --- a/tests/auto/qml/qqmlecmascript/data/functionAssignment.1.qml +++ b/tests/auto/qml/qqmlecmascript/data/functionAssignment.1.qml @@ -2,4 +2,6 @@ import Qt.test 1.0 MyQmlObject { property variant a: function myFunction() { return 2; } + property variant b: Qt.binding(function() { return 2; }) + property var c: Qt.binding(function() { return 2; }) } diff --git a/tests/auto/qml/qqmlecmascript/data/functionAssignment.2.qml b/tests/auto/qml/qqmlecmascript/data/functionAssignment.2.qml index 0f78eaf1dc..3d8fd85a88 100644 --- a/tests/auto/qml/qqmlecmascript/data/functionAssignment.2.qml +++ b/tests/auto/qml/qqmlecmascript/data/functionAssignment.2.qml @@ -24,7 +24,7 @@ MyQmlObject { function myFunction() { return aNumber * 10; } - a = myFunction; + a = Qt.binding(myFunction); } property QtObject obj: QtObject { @@ -34,7 +34,7 @@ MyQmlObject { } } onAssignWithThisChanged: { - a = obj.myFunction; + a = Qt.binding(obj.myFunction); } onAssignToPropertyFromJsFileChanged: { @@ -47,8 +47,8 @@ MyQmlObject { property Text text: Text { } onAssignToValueTypeChanged: { - text.font.pixelSize = (function() { return aNumber * 10; }) - a = (function() { return text.font.pixelSize; }) + text.font.pixelSize = Qt.binding(function() { return aNumber * 10; }) + a = Qt.binding(function() { return text.font.pixelSize; }) } @@ -57,17 +57,17 @@ MyQmlObject { onAssignFuncWithoutReturnChanged: { function myFunction() { } - a = myFunction; + a = Qt.binding(myFunction); } onAssignWrongTypeChanged: { function myFunction() { return 'a string'; } - aNumber = myFunction; + aNumber = Qt.binding(myFunction); } onAssignWrongTypeToValueTypeChanged: { - text.font.pixelSize = (function() { return 'a string'; }) + text.font.pixelSize = Qt.binding(function() { return 'a string'; }) } } diff --git a/tests/auto/qml/qqmlecmascript/data/functionAssignment.3.qml b/tests/auto/qml/qqmlecmascript/data/functionAssignment.3.qml new file mode 100644 index 0000000000..c34a868949 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/functionAssignment.3.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 + +Item { + property int t1: 1 + property int t2: 2 + + function randomNumber() { + return 4; + } + + Component.onCompleted: { + // shouldn't "convert" the randomNumber function into a binding permanently + t1 = Qt.binding(randomNumber) + + // therefore, the following assignment should fail. + t2 = randomNumber + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/functionAssignment.js b/tests/auto/qml/qqmlecmascript/data/functionAssignment.js index 14daa7629f..3ba4e193e6 100644 --- a/tests/auto/qml/qqmlecmascript/data/functionAssignment.js +++ b/tests/auto/qml/qqmlecmascript/data/functionAssignment.js @@ -1,6 +1,6 @@ function bindProperty() { - a = (function(){ return aNumber * 10 }) + a = Qt.binding(function(){ return aNumber * 10 }) } @@ -13,5 +13,5 @@ var testObj = new TestObject() function bindPropertyWithThis() { - a = testObj.bindFunction + a = Qt.binding(testObj.bindFunction) } diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.11.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.11.qml new file mode 100644 index 0000000000..63be26717e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.11.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 + +Item { + property bool test: false + property var fnResult: testFunction(5) + property var f1: testFunction + property var f2 + + function testFunction(x) { + return x; + } + + Component.onCompleted: { + f2 = testFunction; + if (fnResult != 5) return; + if (f1(6) != 6) return; + if (f2(7) != 7) return; + if (f1 != f2) return; + test = true; + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.12.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.12.qml new file mode 100644 index 0000000000..3510bd2350 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.12.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +Item { + property bool test: false + property var nullOne: null + property var nullTwo + property var undefOne: undefined + property var undefTwo + + Component.onCompleted: { + nullTwo = null; + undefTwo = undefined; + if (nullOne != null) return; + if (nullOne != nullTwo) return; + if (undefOne != undefined) return; + if (undefOne != undefTwo) return; + test = true; + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.13.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.13.qml new file mode 100644 index 0000000000..14c7c677ae --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.13.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +Item { + property bool test: false + property var f: b + 12 + property int a: 100 + property int b: testFunction() + + function testFunction() { + return a * 3; + } + + Component.onCompleted: { + if (f != 312) return; + a = 120; + if (f != 372) return; + test = true; + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.14.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.14.qml new file mode 100644 index 0000000000..a1e26661bb --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.14.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 + +Item { + property bool test: false + property var f + property int a: 100 + property int b + + function testFunction() { + return a * 3; + } + + Component.onCompleted: { + b = Qt.binding(testFunction); + f = Qt.binding(function() { return b + 12; }); + if (f != 312) return; + a = 120; + if (f != 372) return; + test = true; + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.15.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.15.qml new file mode 100644 index 0000000000..5e5071fc2d --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.15.qml @@ -0,0 +1,20 @@ +import QtQuick 2.0 + +Item { + property bool test: false + property var storedBinding: [ Qt.binding(function() { return testFunction() + 12; }) ] + property int a: 100 + property int b + + function testFunction() { + return a * 3; + } + + Component.onCompleted: { + b = storedBinding[0]; + if (b != 312) return; + a = 120; + if (b != 372) return; + test = true; + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 79eaa3316f..861ff2e641 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -195,6 +195,7 @@ private slots: void functionAssignment_fromJS(); void functionAssignment_fromJS_data(); void functionAssignmentfromJS_invalid(); + void functionAssignment_afterBinding(); void eval(); void function(); void functionException(); @@ -3792,6 +3793,11 @@ void tst_qqmlecmascript::propertyVar_data() QTest::newRow("literal property assignment") << testFileUrl("propertyVar.8.qml"); QTest::newRow("qobject property assignment") << testFileUrl("propertyVar.9.qml"); QTest::newRow("base class var property assignment") << testFileUrl("propertyVar.10.qml"); + QTest::newRow("javascript function assignment") << testFileUrl("propertyVar.11.qml"); + QTest::newRow("javascript special assignment") << testFileUrl("propertyVar.12.qml"); + QTest::newRow("declarative binding assignment") << testFileUrl("propertyVar.13.qml"); + QTest::newRow("imperative binding assignment") << testFileUrl("propertyVar.14.qml"); + QTest::newRow("stored binding assignment") << testFileUrl("propertyVar.15.qml"); } void tst_qqmlecmascript::propertyVar() @@ -4639,7 +4645,7 @@ void tst_qqmlecmascript::sequenceConversionWrite() QVERIFY(seq != 0); // we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work. - QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QVariantList to void"); + QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QVariantList to an unregistered type"); QTest::ignoreMessage(QtWarningMsg, warningOne.toAscii().constData()); QMetaObject::invokeMethod(object, "performTest"); @@ -5054,9 +5060,13 @@ void tst_qqmlecmascript::functionAssignment_fromBinding() QQmlComponent component(&engine, testFileUrl("functionAssignment.1.qml")); QString url = component.url().toString(); - QString warning = url + ":4:25: Unable to assign a function to a property."; - QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); - + QString w1 = url + ":4:25: Unable to assign a function to a property of any type other than var."; + QString w2 = url + ":5:25: Invalid use of Qt.binding() in a binding declaration."; + QString w3 = url + ":6:21: Invalid use of Qt.binding() in a binding declaration."; + QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, w2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, w3.toLatin1().constData()); + MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); QVERIFY(o != 0); @@ -5123,6 +5133,24 @@ void tst_qqmlecmascript::functionAssignmentfromJS_invalid() delete o; } +void tst_qqmlecmascript::functionAssignment_afterBinding() +{ + QQmlComponent component(&engine, testFileUrl("functionAssignment.3.qml")); + + QString url = component.url().toString(); + //QString w1 = url + ":16: Error: Cannot assign JavaScript function to int"; // for now, function assignment = binding assignment + QString w1 = QLatin1String("WARNING: function assignment is DEPRECATED and will be removed! Wrap RHS in Qt.binding(): ") + url + QLatin1String(":16"); + QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData()); + + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("t1"), QVariant::fromValue<int>(4)); // should have bound + //QCOMPARE(o->property("t2"), QVariant::fromValue<int>(2)); // should not have changed + QCOMPARE(o->property("t2"), QVariant::fromValue<int>(4)); // for now, function assignment = binding assignment + + delete o; +} + void tst_qqmlecmascript::eval() { QQmlComponent component(&engine, testFileUrl("eval.qml")); diff --git a/tests/auto/qml/qqmlimageprovider/qqmlimageprovider.pro b/tests/auto/qml/qqmlimageprovider/qqmlimageprovider.pro deleted file mode 100644 index 9feeee15fd..0000000000 --- a/tests/auto/qml/qqmlimageprovider/qqmlimageprovider.pro +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG += testcase -TARGET = tst_qqmlimageprovider -macx:CONFIG -= app_bundle - -SOURCES += tst_qqmlimageprovider.cpp - -CONFIG += parallel_test - -QT += core-private gui-private qml-private quick-private network testlib diff --git a/tests/auto/qml/qqmlimageprovider/tst_qqmlimageprovider.cpp b/tests/auto/qml/qqmlimageprovider/tst_qqmlimageprovider.cpp deleted file mode 100644 index bc53544566..0000000000 --- a/tests/auto/qml/qqmlimageprovider/tst_qqmlimageprovider.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qtest.h> -#include <QtTest/QtTest> -#include <QtQml/qqmlengine.h> -#include <QtQml/qqmlimageprovider.h> -#include <private/qquickimage_p.h> -#include <QImageReader> -#include <QWaitCondition> - -Q_DECLARE_METATYPE(QQmlImageProvider*); - -class tst_qqmlimageprovider : public QObject -{ - Q_OBJECT -public: - tst_qqmlimageprovider() - { - } - -private slots: - void requestImage_sync_data(); - void requestImage_sync(); - void requestImage_async_data(); - void requestImage_async(); - - void requestPixmap_sync_data(); - void requestPixmap_sync(); - void requestPixmap_async(); - - void removeProvider_data(); - void removeProvider(); - - void threadTest(); - -private: - QString newImageFileName() const; - void fillRequestTestsData(const QString &id); - void runTest(bool async, QQmlImageProvider *provider); -}; - - -class TestQImageProvider : public QQmlImageProvider -{ -public: - TestQImageProvider(bool *deleteWatch = 0) - : QQmlImageProvider(Image), deleteWatch(deleteWatch) - { - } - - ~TestQImageProvider() - { - if (deleteWatch) - *deleteWatch = true; - } - - QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) - { - lastImageId = id; - - if (id == QLatin1String("no-such-file.png")) - return QImage(); - - int width = 100; - int height = 100; - QImage image(width, height, QImage::Format_RGB32); - if (size) - *size = QSize(width, height); - if (requestedSize.isValid()) - image = image.scaled(requestedSize); - return image; - } - - bool *deleteWatch; - QString lastImageId; -}; -Q_DECLARE_METATYPE(TestQImageProvider*); - - -class TestQPixmapProvider : public QQmlImageProvider -{ -public: - TestQPixmapProvider(bool *deleteWatch = 0) - : QQmlImageProvider(Pixmap), deleteWatch(deleteWatch) - { - } - - ~TestQPixmapProvider() - { - if (deleteWatch) - *deleteWatch = true; - } - - QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize) - { - lastImageId = id; - - if (id == QLatin1String("no-such-file.png")) - return QPixmap(); - - int width = 100; - int height = 100; - QPixmap image(width, height); - if (size) - *size = QSize(width, height); - if (requestedSize.isValid()) - image = image.scaled(requestedSize); - return image; - } - - bool *deleteWatch; - QString lastImageId; -}; -Q_DECLARE_METATYPE(TestQPixmapProvider*); - - -QString tst_qqmlimageprovider::newImageFileName() const -{ - // need to generate new filenames each time or else images are loaded - // from cache and we won't get loading status changes when testing - // async loading - static int count = 0; - return QString("image://test/image-%1.png").arg(count++); -} - -void tst_qqmlimageprovider::fillRequestTestsData(const QString &id) -{ - QTest::addColumn<QString>("source"); - QTest::addColumn<QString>("imageId"); - QTest::addColumn<QString>("properties"); - QTest::addColumn<QSize>("size"); - QTest::addColumn<QString>("error"); - - QString fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " simple test")) - << "image://test/" + fileName << fileName << "" << QSize(100,100) << ""; - - fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " simple test with capitalization"))//As it's a URL, should make no difference - << "image://Test/" + fileName << fileName << "" << QSize(100,100) << ""; - - fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " url with no id")) - << "image://test/" + fileName << "" + fileName << "" << QSize(100,100) << ""; - - fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " url with path")) - << "image://test/test/path" + fileName << "test/path" + fileName << "" << QSize(100,100) << ""; - - fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " url with fragment")) - << "image://test/faq.html?#question13" + fileName << "faq.html?#question13" + fileName << "" << QSize(100,100) << ""; - - fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " url with query")) - << "image://test/cgi-bin/drawgraph.cgi?type=pie&color=green" + fileName << "cgi-bin/drawgraph.cgi?type=pie&color=green" + fileName - << "" << QSize(100,100) << ""; - - fileName = newImageFileName(); - QTest::newRow(QTest::toString(id + " scaled image")) - << "image://test/" + fileName << fileName << "sourceSize: \"80x30\"" << QSize(80,30) << ""; - - QTest::newRow(QTest::toString(id + " missing")) - << "image://test/no-such-file.png" << "no-such-file.png" << "" << QSize(100,100) - << "file::2:1: QML Image: Failed to get image from provider: image://test/no-such-file.png"; - - QTest::newRow(QTest::toString(id + " unknown provider")) - << "image://bogus/exists.png" << "" << "" << QSize() - << "file::2:1: QML Image: Invalid image provider: image://bogus/exists.png"; -} - -void tst_qqmlimageprovider::runTest(bool async, QQmlImageProvider *provider) -{ - QFETCH(QString, source); - QFETCH(QString, imageId); - QFETCH(QString, properties); - QFETCH(QSize, size); - QFETCH(QString, error); - - if (!error.isEmpty()) - QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); - - QQmlEngine engine; - - engine.addImageProvider("test", provider); - QVERIFY(engine.imageProvider("test") != 0); - - QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; " - + (async ? "asynchronous: true; " : "") - + properties + " }"; - QQmlComponent component(&engine); - component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); - QQuickImage *obj = qobject_cast<QQuickImage*>(component.create()); - QVERIFY(obj != 0); - - if (async) - QTRY_VERIFY(obj->status() == QQuickImage::Loading); - - QCOMPARE(obj->source(), QUrl(source)); - - if (error.isEmpty()) { - if (async) - QTRY_VERIFY(obj->status() == QQuickImage::Ready); - else - QVERIFY(obj->status() == QQuickImage::Ready); - if (QByteArray(QTest::currentDataTag()).startsWith("qimage")) - QCOMPARE(static_cast<TestQImageProvider*>(provider)->lastImageId, imageId); - else - QCOMPARE(static_cast<TestQPixmapProvider*>(provider)->lastImageId, imageId); - - QCOMPARE(obj->width(), qreal(size.width())); - QCOMPARE(obj->height(), qreal(size.height())); - QCOMPARE(obj->fillMode(), QQuickImage::Stretch); - QCOMPARE(obj->progress(), 1.0); - } else { - if (async) - QTRY_VERIFY(obj->status() == QQuickImage::Error); - else - QVERIFY(obj->status() == QQuickImage::Error); - } - - delete obj; -} - -void tst_qqmlimageprovider::requestImage_sync_data() -{ - fillRequestTestsData("qimage|sync"); -} - -void tst_qqmlimageprovider::requestImage_sync() -{ - bool deleteWatch = false; - runTest(false, new TestQImageProvider(&deleteWatch)); - QVERIFY(deleteWatch); -} - -void tst_qqmlimageprovider::requestImage_async_data() -{ - fillRequestTestsData("qimage|async"); -} - -void tst_qqmlimageprovider::requestImage_async() -{ - bool deleteWatch = false; - runTest(true, new TestQImageProvider(&deleteWatch)); - QVERIFY(deleteWatch); -} - -void tst_qqmlimageprovider::requestPixmap_sync_data() -{ - fillRequestTestsData("qpixmap"); -} - -void tst_qqmlimageprovider::requestPixmap_sync() -{ - bool deleteWatch = false; - runTest(false, new TestQPixmapProvider(&deleteWatch)); - QVERIFY(deleteWatch); -} - -void tst_qqmlimageprovider::requestPixmap_async() -{ - QQmlEngine engine; - QQmlImageProvider *provider = new TestQPixmapProvider(); - - engine.addImageProvider("test", provider); - QVERIFY(engine.imageProvider("test") != 0); - - // pixmaps are loaded synchronously regardless of 'asynchronous' value - QString componentStr = "import QtQuick 2.0\nImage { asynchronous: true; source: \"image://test/pixmap-async-test.png\" }"; - QQmlComponent component(&engine); - component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); - QQuickImage *obj = qobject_cast<QQuickImage*>(component.create()); - QVERIFY(obj != 0); - - delete obj; -} - -void tst_qqmlimageprovider::removeProvider_data() -{ - QTest::addColumn<QQmlImageProvider*>("provider"); - - QTest::newRow("qimage") << static_cast<QQmlImageProvider*>(new TestQImageProvider); - QTest::newRow("qpixmap") << static_cast<QQmlImageProvider*>(new TestQPixmapProvider); -} - -void tst_qqmlimageprovider::removeProvider() -{ - QFETCH(QQmlImageProvider*, provider); - - QQmlEngine engine; - - engine.addImageProvider("test", provider); - QVERIFY(engine.imageProvider("test") != 0); - - // add provider, confirm it works - QString componentStr = "import QtQuick 2.0\nImage { source: \"" + newImageFileName() + "\" }"; - QQmlComponent component(&engine); - component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); - QQuickImage *obj = qobject_cast<QQuickImage*>(component.create()); - QVERIFY(obj != 0); - - QCOMPARE(obj->status(), QQuickImage::Ready); - - // remove the provider and confirm - QString fileName = newImageFileName(); - QString error("file::2:1: QML Image: Invalid image provider: " + fileName); - QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); - - engine.removeImageProvider("test"); - - obj->setSource(QUrl(fileName)); - QCOMPARE(obj->status(), QQuickImage::Error); - - delete obj; -} - -class TestThreadProvider : public QQmlImageProvider -{ - public: - TestThreadProvider() : QQmlImageProvider(Image), ok(false) {} - - ~TestThreadProvider() {} - - QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) - { - mutex.lock(); - if (!ok) - cond.wait(&mutex); - mutex.unlock(); - QVector<int> v; - for (int i = 0; i < 10000; i++) - v.prepend(i); //do some computation - QImage image(50,50, QImage::Format_RGB32); - image.fill(QColor(id).rgb()); - if (size) - *size = image.size(); - if (requestedSize.isValid()) - image = image.scaled(requestedSize); - return image; - } - - QWaitCondition cond; - QMutex mutex; - bool ok; -}; - - -void tst_qqmlimageprovider::threadTest() -{ - QQmlEngine engine; - - TestThreadProvider *provider = new TestThreadProvider; - - engine.addImageProvider("test_thread", provider); - QVERIFY(engine.imageProvider("test_thread") != 0); - - QString componentStr = "import QtQuick 2.0\nItem { \n" - "Image { source: \"image://test_thread/blue\"; asynchronous: true; }\n" - "Image { source: \"image://test_thread/red\"; asynchronous: true; }\n" - "Image { source: \"image://test_thread/green\"; asynchronous: true; }\n" - "Image { source: \"image://test_thread/yellow\"; asynchronous: true; }\n" - " }"; - QQmlComponent component(&engine); - component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); - QObject *obj = component.create(); - //MUST not deadlock - QVERIFY(obj != 0); - QList<QQuickImage *> images = obj->findChildren<QQuickImage *>(); - QCOMPARE(images.count(), 4); - QTest::qWait(100); - foreach (QQuickImage *img, images) { - QCOMPARE(img->status(), QQuickImage::Loading); - } - provider->ok = true; - provider->cond.wakeAll(); - QTest::qWait(250); - foreach (QQuickImage *img, images) { - QTRY_VERIFY(img->status() == QQuickImage::Ready); - } -} - - -QTEST_MAIN(tst_qqmlimageprovider) - -#include "tst_qqmlimageprovider.moc" diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp index f2c50ddbef..ca48f027e0 100644 --- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp +++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp @@ -211,10 +211,10 @@ void tst_QQmlMetaObject::property() QCOMPARE(prop.name(), "test"); QCOMPARE(QByteArray(prop.typeName()), cppTypeName); - QEXPECT_FAIL("QtObject", "prop.type() returns UserType for QtObject properties", Continue); - QEXPECT_FAIL("alias-2", "prop.type() returns UserType for QtObject properties", Continue); if (prop.userType() < QMetaType::User) QCOMPARE(prop.type(), QVariant::Type(cppType)); + else + QCOMPARE(prop.type(), QVariant::UserType); QCOMPARE(prop.userType(), cppType); QVERIFY(!prop.isConstant()); @@ -244,12 +244,15 @@ void tst_QQmlMetaObject::property() QVERIFY(prop.notifySignalIndex() != -1); QMetaMethod signal = prop.notifySignal(); QCOMPARE(signal.methodType(), QMetaMethod::Signal); - QCOMPARE(signal.signature(), "testChanged()"); + QCOMPARE(signal.name(), QByteArray("testChanged")); + QCOMPARE(signal.methodSignature(), QByteArray("testChanged()")); QCOMPARE(signal.access(), QMetaMethod::Protected); + QCOMPARE(signal.parameterCount(), 0); QCOMPARE(signal.parameterTypes(), QList<QByteArray>()); QCOMPARE(signal.parameterNames(), QList<QByteArray>()); QCOMPARE(signal.tag(), ""); QCOMPARE(signal.typeName(), ""); + QCOMPARE(signal.returnType(), int(QMetaType::Void)); QSignalSpy changedSpy(object, SIGNAL(testChanged())); QObject::connect(object, SIGNAL(testChanged()), object, SLOT(deleteLater())); @@ -277,62 +280,73 @@ void tst_QQmlMetaObject::method_data() QTest::addColumn<QString>("testFile"); QTest::addColumn<QString>("signature"); QTest::addColumn<QMetaMethod::MethodType>("methodType"); + QTest::addColumn<int>("returnType"); QTest::addColumn<QString>("returnTypeName"); + QTest::addColumn<QList<int> >("parameterTypes"); QTest::addColumn<QList<QByteArray> >("parameterTypeNames"); QTest::addColumn<QList<QByteArray> >("parameterNames"); QTest::newRow("testFunction()") << "method.1.qml" << "testFunction()" << QMetaMethod::Slot - << "QVariant" + << int(QMetaType::QVariant) << "QVariant" + << QList<int>() << QList<QByteArray>() << QList<QByteArray>(); QTest::newRow("testFunction(foo)") << "method.2.qml" << "testFunction(QVariant)" << QMetaMethod::Slot - << "QVariant" + << int(QMetaType::QVariant) << "QVariant" + << (QList<int>() << QMetaType::QVariant) << (QList<QByteArray>() << "QVariant") << (QList<QByteArray>() << "foo"); QTest::newRow("testFunction(foo, bar, baz)") << "method.3.qml" << "testFunction(QVariant,QVariant,QVariant)" << QMetaMethod::Slot - << "QVariant" + << int(QMetaType::QVariant) << "QVariant" + << (QList<int>() << QMetaType::QVariant << QMetaType::QVariant << QMetaType::QVariant) << (QList<QByteArray>() << "QVariant" << "QVariant" << "QVariant") << (QList<QByteArray>() << "foo" << "bar" << "baz"); QTest::newRow("testSignal") << "signal.1.qml" << "testSignal()" << QMetaMethod::Signal - << "" + << int(QMetaType::Void) << "" + << QList<int>() << QList<QByteArray>() << QList<QByteArray>(); QTest::newRow("testSignal(string foo)") << "signal.2.qml" << "testSignal(QString)" << QMetaMethod::Signal - << "" + << int(QMetaType::Void) << "" + << (QList<int>() << QMetaType::QString) << (QList<QByteArray>() << "QString") << (QList<QByteArray>() << "foo"); QTest::newRow("testSignal(int foo, bool bar, real baz)") << "signal.3.qml" << "testSignal(int,bool,double)" << QMetaMethod::Signal - << "" + << int(QMetaType::Void) << "" + << (QList<int>() << QMetaType::Int << QMetaType::Bool << QMetaType::Double) << (QList<QByteArray>() << "int" << "bool" << "double") << (QList<QByteArray>() << "foo" << "bar" << "baz"); QTest::newRow("testSignal(variant foo, var bar)") << "signal.4.qml" << "testSignal(QVariant,QVariant)" << QMetaMethod::Signal - << "" + << int(QMetaType::Void) << "" + << (QList<int>() << QMetaType::QVariant << QMetaType::QVariant) << (QList<QByteArray>() << "QVariant" << "QVariant") << (QList<QByteArray>() << "foo" << "bar"); QTest::newRow("testSignal(color foo, date bar, url baz)") << "signal.5.qml" << "testSignal(QColor,QDateTime,QUrl)" << QMetaMethod::Signal - << "" + << int(QMetaType::Void) << "" + << (QList<int>() << QMetaType::QColor << QMetaType::QDateTime << QMetaType::QUrl) << (QList<QByteArray>() << "QColor" << "QDateTime" << "QUrl") << (QList<QByteArray>() << "foo" << "bar" << "baz"); QTest::newRow("testSignal(double foo)") << "signal.6.qml" << "testSignal(double)" << QMetaMethod::Signal - << "" + << int(QMetaType::Void) << "" + << (QList<int>() << QMetaType::Double) << (QList<QByteArray>() << "double") << (QList<QByteArray>() << "foo"); } @@ -342,10 +356,13 @@ void tst_QQmlMetaObject::method() QFETCH(QString, testFile); QFETCH(QString, signature); QFETCH(QMetaMethod::MethodType, methodType); + QFETCH(int, returnType); QFETCH(QString, returnTypeName); + QFETCH(QList<int>, parameterTypes); QFETCH(QList<QByteArray>, parameterTypeNames); QFETCH(QList<QByteArray>, parameterNames); + QCOMPARE(parameterTypes.size(), parameterTypeNames.size()); QCOMPARE(parameterTypeNames.size(), parameterNames.size()); QQmlEngine engine; @@ -361,12 +378,21 @@ void tst_QQmlMetaObject::method() QMetaMethod method = mo->method(mo->methodOffset()); QCOMPARE(method.methodType(), methodType); - QCOMPARE(QString::fromUtf8(method.signature()), signature); + QCOMPARE(QString::fromUtf8(method.methodSignature().constData()), signature); QCOMPARE(method.access(), QMetaMethod::Protected); + + QString computedName = signature.left(signature.indexOf('(')); + QCOMPARE(QString::fromUtf8(method.name()), computedName); + + QCOMPARE(method.parameterCount(), parameterTypes.size()); + for (int i = 0; i < parameterTypes.size(); ++i) + QCOMPARE(method.parameterType(i), parameterTypes.at(i)); QCOMPARE(method.parameterTypes(), parameterTypeNames); QCOMPARE(method.parameterNames(), parameterNames); QCOMPARE(method.tag(), ""); + QCOMPARE(QString::fromUtf8(method.typeName()), returnTypeName); + QCOMPARE(method.returnType(), returnType); delete object; } diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 5ef8937dc1..aa22450bd3 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -161,7 +161,7 @@ void tst_qqmlproperty::qmlmetaproperty() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Invalid); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -264,7 +264,7 @@ void tst_qqmlproperty::qmlmetaproperty_object() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Invalid); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -311,7 +311,7 @@ void tst_qqmlproperty::qmlmetaproperty_object() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Property); QCOMPARE(prop.isProperty(), true); QCOMPARE(prop.isWritable(), false); @@ -365,7 +365,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Invalid); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -412,7 +412,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Property); QCOMPARE(prop.isProperty(), true); QCOMPARE(prop.isWritable(), false); @@ -461,7 +461,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QCOMPARE(QString(prop.method().signature()), QString("clicked()")); + QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()")); QCOMPARE(prop.type(), QQmlProperty::SignalProperty); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -509,7 +509,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()")); + QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()")); QCOMPARE(prop.type(), QQmlProperty::SignalProperty); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -562,7 +562,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Invalid); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -609,7 +609,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Property); QCOMPARE(prop.isProperty(), true); QCOMPARE(prop.isWritable(), false); @@ -663,7 +663,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Invalid); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -710,7 +710,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QVERIFY(prop.method().signature() == 0); + QVERIFY(!prop.method().isValid()); QCOMPARE(prop.type(), QQmlProperty::Property); QCOMPARE(prop.isProperty(), true); QCOMPARE(prop.isWritable(), false); @@ -759,7 +759,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QCOMPARE(QString(prop.method().signature()), QString("clicked()")); + QCOMPARE(QString(prop.method().methodSignature()), QString("clicked()")); QCOMPARE(prop.type(), QQmlProperty::SignalProperty); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); @@ -807,7 +807,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QCOMPARE(prop.connectNotifySignal(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); QCOMPARE(prop.connectNotifySignal(obj, -1), false); - QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()")); + QCOMPARE(QString(prop.method().methodSignature()), QString("oddlyNamedNotifySignal()")); QCOMPARE(prop.type(), QQmlProperty::SignalProperty); QCOMPARE(prop.isProperty(), false); QCOMPARE(prop.isWritable(), false); diff --git a/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.2.qml b/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.2.qml new file mode 100644 index 0000000000..0da717ba5c --- /dev/null +++ b/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.2.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import Test 1.0 + +MyTypeObject { + property int value: 10 + rect.y: Qt.binding(function() { return value; }); // error. + + Component.onCompleted: { + rect.x = 5; + rect.x = (function() { return value; }); // error. + } +} diff --git a/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.qml b/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.qml index a65218669b..9b10803649 100644 --- a/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.qml +++ b/tests/auto/qml/qqmlvaluetypes/data/bindingAssignment.qml @@ -1,7 +1,12 @@ +import QtQuick 2.0 import Test 1.0 MyTypeObject { property int value: 10 rect.x: value + + Component.onCompleted: { + rect.y = Qt.binding(function() { return value + 5; }); + } } diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 0aa223e733..54791fc340 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -871,17 +871,37 @@ void tst_qqmlvaluetypes::color() // Test bindings can write to value types void tst_qqmlvaluetypes::bindingAssignment() { + // binding declaration + { QQmlComponent component(&engine, testFileUrl("bindingAssignment.qml")); MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create()); QVERIFY(object != 0); QCOMPARE(object->rect().x(), 10); + QCOMPARE(object->rect().y(), 15); object->setProperty("value", QVariant(92)); QCOMPARE(object->rect().x(), 92); + QCOMPARE(object->rect().y(), 97); delete object; + } + + // function assignment should fail without crashing + { + QString warning1 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":6:13: Invalid use of Qt.binding() in a binding declaration."); + QString warning2 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":10: Error: Cannot assign JavaScript function to value-type property"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); + QQmlComponent component(&engine, testFileUrl("bindingAssignment.2.qml")); + MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->rect().x(), 5); + object->setProperty("value", QVariant(92)); + QCOMPARE(object->rect().x(), 5); + delete object; + } } // Test bindings can read from value types |