/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** 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_END_LICENSE$
**
****************************************************************************/
void aliasToCompositeElement();
void realToInt();
void urlProperty();
+ void urlPropertyWithEncoding();
+ void urlListPropertyWithEncoding();
void dynamicString();
void include();
void signalHandlers();
QMetaObject::invokeMethod(object, "killOther");
QVERIFY(createdQmlObject);
- QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(createdQmlObject);
for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
if (createdQmlObject) {
QTest::qWait(100);
- QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
}
}
QVERIFY(!createdQmlObject);
QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
QMetaObject::invokeMethod(object, "killMe");
QVERIFY(object);
- QTest::qWait(0);
- QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(!object);
}
QMetaObject::invokeMethod(o, "destroy");
- QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
QMetaObject::invokeMethod(object, "performGc");
}
if (i % 10 == 0) {
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
}
}
delete object;
}
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, expectedDtorCount);
}
-//QTBUG-9367
void tst_qdeclarativeecmascript::regExpBug()
{
- QDeclarativeComponent component(&engine, testFileUrl("regExp.qml"));
- MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
- QVERIFY(object != 0);
- QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
- delete object;
+ //QTBUG-9367
+ {
+ QDeclarativeComponent component(&engine, testFileUrl("regExp.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
+ delete object;
+ }
+
+ //QTBUG-23068
+ {
+ QString err = QString(QLatin1String("%1:6 Invalid property assignment: regular expression expected; use /pattern/ syntax\n")).arg(testFileUrl("regExp.2.qml").toString());
+ QDeclarativeComponent component(&engine, testFileUrl("regExp.2.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(!object);
+ QCOMPARE(component.errorString(), err);
+ }
}
static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
engine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(own.object == 0);
engine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(own.object != 0);
delete object;
}
- QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(source.value != 0);
}
}
engine.collectGarbage();
- QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QVERIFY(source.value == 0);
}
static void gc(QDeclarativeEngine &engine)
{
engine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
}
void tst_qdeclarativeecmascript::propertyVarOwnership()
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignCircular");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QObject *rootObject = object->property("vp").value<QObject*>();
QVERIFY(rootObject != 0);
QObject *childObject = rootObject->findChild<QObject*>("text");
QMetaObject::invokeMethod(childObject, "constructQObject"); // creates a reference to a constructed QObject.
QWeakPointer<QObject> qobjectGuard(childObject->property("vp").value<QObject*>()); // get the pointer prior to processing deleteLater events.
QVERIFY(!qobjectGuard.isNull());
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(!qobjectGuard.isNull());
QMetaObject::invokeMethod(object, "deassignCircular");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(qobjectGuard.isNull()); // should have been collected now.
delete object;
}
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignVarProp");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QObject *rect = object->property("vp").value<QObject*>();
QObject *text = rect->findChild<QObject*>("textOne");
QObject *text2 = rect->findChild<QObject*>("textTwo");
// now reparent the "Image" object (currently, it has JS ownership)
image->setParent(text); // shouldn't be collected after deassignVp now, since has a parent.
QMetaObject::invokeMethod(text2, "deassignVp");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QCOMPARE(text->property("textCanary").toInt(), 11);
QCOMPARE(text2->property("textCanary").toInt(), 22);
QVERIFY(!imageGuard.isNull()); // should still be alive.
QCOMPARE(image->property("imageCanary").toInt(), 13); // still able to access var properties
QMetaObject::invokeMethod(object, "deassignVarProp"); // now deassign the root-object's vp, causing gc of rect+text+text2
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(imageGuard.isNull()); // should now have been deleted, due to parent being deleted.
delete object;
}
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignVarProp");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QObject *rect = object->property("vp").value<QObject*>();
QObject *text = rect->findChild<QObject*>("textOne");
QObject *text2 = rect->findChild<QObject*>("textTwo");
// now reparent the "Image" object (currently, it has JS ownership)
image->setParent(object); // reparented to base object. after deassignVarProp, the ctxt will be invalid.
QMetaObject::invokeMethod(object, "deassignVarProp"); // now deassign the root-object's vp, causing gc of rect+text+text2
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(!imageGuard.isNull()); // should still be alive.
QVERIFY(!image->property("imageCanary").isValid()); // but varProperties won't be available (null context).
delete object;
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignCircular"); // cause assignment and gc
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QCOMPARE(object->property("canaryInt"), QVariant(5));
QVariant canaryResourceVariant = object->property("canaryResource");
QVERIFY(canaryResourceVariant.isValid());
QPixmap canaryResourcePixmap = canaryResourceVariant.value<QPixmap>();
canaryResourceVariant = QVariant(); // invalidate it to remove one copy of the pixmap from memory.
QMetaObject::invokeMethod(object, "deassignCanaryResource"); // remove one copy of the pixmap from memory
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(!canaryResourcePixmap.isDetached()); // two copies extant - this and the propertyVar.vp.vp.vp.vp.memoryHog.
QMetaObject::invokeMethod(object, "deassignCircular"); // cause deassignment and gc
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QCOMPARE(object->property("canaryInt"), QVariant(2));
QCOMPARE(object->property("canaryResource"), QVariant(1));
QVERIFY(canaryResourcePixmap.isDetached()); // now detached, since orig copy was member of qdvmemo which was deleted.
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignCircular");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QObject *rootObject = object->property("vp").value<QObject*>();
QVERIFY(rootObject != 0);
QObject *childObject = rootObject->findChild<QObject*>("text");
QCOMPARE(rootObject->property("rectCanary").toInt(), 5);
QCOMPARE(childObject->property("textCanary").toInt(), 10);
QMetaObject::invokeMethod(object, "deassignCircular");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(rootObjectTracker.isNull()); // should have been collected
QVERIFY(childObjectTracker.isNull()); // should have been collected
delete object;
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignCircular"); // cause assignment and gc
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
// we want to be able to track when the varProperties array of the last metaobject is disposed
QObject *cco5 = object->property("varProperty").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>();
QObject *ico5 = object->property("varProperty").value<QObject*>()->property("inheritanceVarProperty").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>();
}
// now we deassign the var prop, which should trigger collection of item subtrees.
QMetaObject::invokeMethod(object, "deassignCircular"); // cause deassignment and gc
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
// ensure that there are only weak handles to the underlying varProperties array remaining.
gc(engine);
QCOMPARE(propertyVarWeakRefCallbackCount, 2); // should have been called for both, since all refs should be weak.
QObject *object = component.create();
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "assignCircular");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QObject *rootObject = object->property("vp").value<QObject*>();
QVERIFY(rootObject != 0);
QObject *childObject = rootObject->findChild<QObject*>("text");
QCOMPARE(childObject->property("textCanary").toInt(), 10);
}
QMetaObject::invokeMethod(object, "deassignCircular");
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
+ QCoreApplication::processEvents();
QVERIFY(propertyVarWeakRefCallbackCount == 1); // should have been collected now.
delete object;
}
QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
delete object;
hrmEngine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 3);
}
QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
delete object;
hrmEngine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 3);
}
QCOMPARE(dtorCount, 0); // due to reference from first to second, second shouldn't be collected.
delete object;
hrmEngine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 3);
}
QCOMPARE(dtorCount, 2); // despite circular references, both will be collected.
delete object;
hrmEngine.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 3);
}
second2->setParent(0);
QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
gc(engine);
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 0); // due to reference from first1 to second2, second2 shouldn't be collected.
delete object1;
delete object2;
hrmEngine1.collectGarbage();
hrmEngine2.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 6);
}
QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
gc(engine);
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 4); // circular references shouldn't keep them alive.
delete object1;
delete object2;
hrmEngine1.collectGarbage();
hrmEngine2.collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 6);
}
delete object1;
delete object2;
hrmEngine1->collectGarbage();
- QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
QCOMPARE(dtorCount, 6);
delete hrmEngine1;
}
}
}
+void tst_qdeclarativeecmascript::urlPropertyWithEncoding()
+{
+ {
+ QDeclarativeComponent component(&engine, testFileUrl("urlProperty.2.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ object->setStringProperty("http://qt-project.org");
+ QUrl encoded;
+ encoded.setEncodedUrl("http://qt-project.org/?get%3cDATA%3e", QUrl::TolerantMode);
+ QCOMPARE(object->urlProperty(), encoded);
+ QCOMPARE(object->value(), 0); // Interpreting URL as string yields canonicalised version
+ QCOMPARE(object->property("result").toBool(), true);
+ }
+}
+
+void tst_qdeclarativeecmascript::urlListPropertyWithEncoding()
+{
+ {
+ QDeclarativeComponent component(&engine, testFileUrl("urlListProperty.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ MySequenceConversionObject *msco1 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco1"));
+ MySequenceConversionObject *msco2 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco2"));
+ MySequenceConversionObject *msco3 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco3"));
+ MySequenceConversionObject *msco4 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco4"));
+ QVERIFY(msco1 != 0 && msco2 != 0 && msco3 != 0 && msco4 != 0);
+ QUrl encoded;
+ encoded.setEncodedUrl("http://qt-project.org/?get%3cDATA%3e", QUrl::TolerantMode);
+ QCOMPARE(msco1->urlListProperty(), (QList<QUrl>() << encoded));
+ QCOMPARE(msco2->urlListProperty(), (QList<QUrl>() << encoded));
+ QCOMPARE(msco3->urlListProperty(), (QList<QUrl>() << encoded << encoded));
+ QCOMPARE(msco4->urlListProperty(), (QList<QUrl>() << encoded << encoded));
+ delete object;
+ }
+}
+
void tst_qdeclarativeecmascript::dynamicString()
{
QDeclarativeComponent component(&engine, testFileUrl("dynamicString.qml"));