diff options
Diffstat (limited to 'tests')
43 files changed, 1261 insertions, 413 deletions
diff --git a/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp b/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp index 98209e218c..43600e226e 100644 --- a/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp +++ b/tests/auto/particles/qquicktrailemitter/tst_qquicktrailemitter.cpp @@ -86,7 +86,7 @@ void tst_qquicktrailemitter::test_basic() QVERIFY(myFuzzyLEQ(d->t, ((qreal)system->timeInt/1000.0))); } - QCOMPARE(system->groupData[1]->size(), 500); + QVERIFY(extremelyFuzzyCompare(system->groupData[1]->size(), 500, 10)); foreach (QQuickParticleData *d, system->groupData[1]->data) { if (d->t == -1) continue; //Particle data unused diff --git a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp index a832c58ae3..5a1148e92e 100644 --- a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp +++ b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp @@ -211,19 +211,8 @@ void tst_QPauseAnimationJob::multiplePauseAnimations() #endif QCOMPARE(animation2.m_updateCurrentTimeCount, 2); - QTest::qWait(550); - -#ifdef Q_OS_WIN - if (animation2.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); -#endif - QVERIFY(animation2.state() == QAbstractAnimationJob::Stopped); - -#ifdef Q_OS_WIN - if (animation2.m_updateCurrentTimeCount != 3) - QEXPECT_FAIL("", winTimerError, Abort); -#endif - QCOMPARE(animation2.m_updateCurrentTimeCount, 3); + QTRY_COMPARE(animation2.state(), QAbstractAnimationJob::Stopped); + QVERIFY(animation2.m_updateCurrentTimeCount >= 3); } void tst_QPauseAnimationJob::pauseAndPropertyAnimations() @@ -240,19 +229,17 @@ void tst_QPauseAnimationJob::pauseAndPropertyAnimations() QTest::qWait(100); animation.start(); - QVERIFY(animation.state() == QAbstractAnimationJob::Running); - QVERIFY(pause.state() == QAbstractAnimationJob::Running); - QCOMPARE(pause.m_updateCurrentTimeCount, 2); + QCOMPARE(animation.state(), QAbstractAnimationJob::Running); - QTest::qWait(animation.totalDuration() + 100); + QTRY_COMPARE(animation.state(), QAbstractAnimationJob::Running); + QVERIFY(pause.state() == QAbstractAnimationJob::Running); + QVERIFY2(pause.m_updateCurrentTimeCount >= 2, + QByteArrayLiteral("pause.m_updateCurrentTimeCount=") + QByteArray::number(pause.m_updateCurrentTimeCount)); -#ifdef Q_OS_WIN - if (animation.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); -#endif - QVERIFY(animation.state() == QAbstractAnimationJob::Stopped); - QVERIFY(pause.state() == QAbstractAnimationJob::Stopped); - QVERIFY(pause.m_updateCurrentTimeCount > 3); + QTRY_COMPARE(animation.state(), QAbstractAnimationJob::Stopped); + QCOMPARE(pause.state(), QAbstractAnimationJob::Stopped); + QVERIFY2(pause.m_updateCurrentTimeCount > 3, + QByteArrayLiteral("pause.m_updateCurrentTimeCount=") + QByteArray::number(pause.m_updateCurrentTimeCount)); } void tst_QPauseAnimationJob::pauseResume() @@ -260,19 +247,15 @@ void tst_QPauseAnimationJob::pauseResume() TestablePauseAnimation animation; animation.setDuration(400); animation.start(); - QVERIFY(animation.state() == QAbstractAnimationJob::Running); + QCOMPARE(animation.state(), QAbstractAnimationJob::Running); QTest::qWait(200); animation.pause(); - QVERIFY(animation.state() == QAbstractAnimationJob::Paused); + QCOMPARE(animation.state(), QAbstractAnimationJob::Paused); animation.start(); QTest::qWait(300); - QVERIFY(animation.state() == QAbstractAnimationJob::Stopped); - -#ifdef Q_OS_WIN - if (animation.m_updateCurrentTimeCount != 3) - QEXPECT_FAIL("", winTimerError, Abort); -#endif - QCOMPARE(animation.m_updateCurrentTimeCount, 3); + QTRY_VERIFY(animation.state() == QAbstractAnimationJob::Stopped); + QVERIFY2(animation.m_updateCurrentTimeCount >= 3, + QByteArrayLiteral("animation.m_updateCurrentTimeCount=") + QByteArray::number(animation.m_updateCurrentTimeCount)); } void tst_QPauseAnimationJob::sequentialPauseGroup() @@ -423,7 +406,7 @@ void tst_QPauseAnimationJob::multipleSequentialGroups() if (group.state() != QAbstractAnimationJob::Stopped) QEXPECT_FAIL("", winTimerError, Abort); #endif - QVERIFY(group.state() == QAbstractAnimationJob::Stopped); + QTRY_VERIFY(group.state() == QAbstractAnimationJob::Stopped); #ifdef Q_OS_WIN if (subgroup1.state() != QAbstractAnimationJob::Stopped) diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index f2b82db630..929b079a51 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -418,22 +418,22 @@ void tst_QQmlProfilerService::pixmapCacheData() QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); // image starting to load - QCOMPARE(m_client->traceMessages[8].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); - QCOMPARE(m_client->traceMessages[8].detailType, (int)QQmlProfilerClient::PixmapLoadingStarted); + QCOMPARE(m_client->traceMessages[16].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[16].detailType, (int)QQmlProfilerClient::PixmapLoadingStarted); // image loaded - QCOMPARE(m_client->traceMessages[9].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); - QCOMPARE(m_client->traceMessages[9].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished); + QCOMPARE(m_client->traceMessages[17].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[17].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished); // image size - QCOMPARE(m_client->traceMessages[10].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); - QCOMPARE(m_client->traceMessages[10].detailType, (int)QQmlProfilerClient::PixmapSizeKnown); - QCOMPARE(m_client->traceMessages[10].line, 2); // width - QCOMPARE(m_client->traceMessages[10].column, 2); // height + QCOMPARE(m_client->traceMessages[18].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[18].detailType, (int)QQmlProfilerClient::PixmapSizeKnown); + QCOMPARE(m_client->traceMessages[18].line, 2); // width + QCOMPARE(m_client->traceMessages[18].column, 2); // height // cache size - QCOMPARE(m_client->traceMessages[11].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); - QCOMPARE(m_client->traceMessages[11].detailType, (int)QQmlProfilerClient::PixmapCacheCountChanged); + QCOMPARE(m_client->traceMessages[19].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[19].detailType, (int)QQmlProfilerClient::PixmapCacheCountChanged); // must end with "EndTrace" QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp index 95674ce6d7..6474a04796 100644 --- a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp +++ b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp @@ -449,6 +449,7 @@ QString QQmlDebugClient::stateString() const case Unavailable: return QLatin1String("Unavailable"); case Enabled: return QLatin1String("Enabled"); } + return QLatin1String("Invalid"); } void QQmlDebugClient::sendMessage(const QByteArray &message) diff --git a/tests/auto/qml/qqmlecmascript/data/misctypetest.qml b/tests/auto/qml/qqmlecmascript/data/misctypetest.qml index 60ff53a2b4..088ede67ec 100644 --- a/tests/auto/qml/qqmlecmascript/data/misctypetest.qml +++ b/tests/auto/qml/qqmlecmascript/data/misctypetest.qml @@ -11,7 +11,7 @@ Item { return mtt.invalidUrl() == mtt.invalidUrl(); } - function test_invalid_url_refequal() + function test_invalid_url_strictequal() { return mtt.invalidUrl() === mtt.invalidUrl(); } @@ -21,7 +21,7 @@ Item { return mtt.validUrl() == mtt.validUrl(); } - function test_valid_url_refequal() + function test_valid_url_strictequal() { return mtt.validUrl() === mtt.validUrl(); } diff --git a/tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml b/tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml new file mode 100644 index 0000000000..8b8601692d --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml @@ -0,0 +1,14 @@ +import QtQml 2.0 +QtObject { + property bool somePropertyEvaluated: false; + + property int someProperty: { + // It's sort of evil to set the property here, but that doesn't mean that + // this expression should get re-evaluated when unrelatedProperty changes later. + somePropertyEvaluated = true + return 20; + } + Component.onCompleted: { + somePropertyEvaluated = false + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml index 52abda1e55..8d08cc5559 100644 --- a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml +++ b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml @@ -140,6 +140,22 @@ Item { if (msco.intListProperty.toString() != expected.toString()) success = false; expected = 7; if (poppedVal != expected) success = false; + + // concat + msco.stringListProperty = [ "one", "two" ] + stringList = [ "hello", "world" ] + stringList = stringList.concat(msco.stringListProperty) + expected = [ "hello", "world", "one", "two" ] + if (stringList.length != expected.length) { + success = false; + } else { + for (var i = 0; i < stringList.length; ++i) { + if (stringList[i] != expected[i]) { + success = false; + break; + } + } + } } property variant variantList: [ 1, 2, 3, 4, 5 ]; diff --git a/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml b/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml index 975be1b2ad..7e85312692 100644 --- a/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml +++ b/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml @@ -57,4 +57,38 @@ QtObject { if (onTestSignal !== undefined) definedHandlerResult = true; } + + property QtObject objWithAlias: QtObject { + id: testObjectWithAlias + + property int count: 0; + property alias countAlias: testObjectWithAlias.count + } + + function testConnectionOnAlias() { + var called = false; + + testObjectWithAlias.onCountAliasChanged.connect(function() { + called = true + }) + + testObjectWithAlias.count++; + return called; + } + + property QtObject objWithAliasHandler: QtObject { + id: testObjectWithAliasHandler + + property bool testSuccess: false + + property int count: 0 + property alias countAlias: testObjectWithAliasHandler.count + onCountAliasChanged: testSuccess = true + } + + function testAliasSignalHandler() { + testObjectWithAliasHandler.testSuccess = false + testObjectWithAliasHandler.count++ + return testObjectWithAliasHandler.testSuccess + } } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 41fa3672bd..22fac2013e 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -106,7 +106,7 @@ public: void MyQmlObject::v8function(QQmlV4Function *function) { - QV8Engine::getV4(function->engine())->current->throwError(QStringLiteral("Exception thrown from within QObject slot")); + QV8Engine::getV4(function->engine())->currentContext()->throwError(QStringLiteral("Exception thrown from within QObject slot")); } static QJSValue script_api(QQmlEngine *engine, QJSEngine *scriptEngine) diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 6b19c13109..7b89709923 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -319,6 +319,7 @@ private slots: void stackLimits(); void idsAsLValues(); void qtbug_34792(); + void noCaptureWhenWritingProperty(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -2267,7 +2268,7 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::ValueRef o, cons QV4::Script program(QV8Engine::getV4(engine)->rootContext, functionSource); program.inheritContext = true; - QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->current; + QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->currentContext(); QV4::Scope scope(ctx); QV4::Scoped<QV4::FunctionObject> function(scope, program.run()); @@ -2295,7 +2296,7 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::ValueRef o, QV4::Script program(QV8Engine::getV4(engine)->rootContext, functionSource); program.inheritContext = true; - QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->current; + QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->currentContext(); QV4::Scope scope(ctx); QV4::Scoped<QV4::FunctionObject> function(scope, program.run()); @@ -2324,7 +2325,7 @@ static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::ValueRef QString functionSource = QLatin1String("(function(object) { return ") + QLatin1String(source) + QLatin1String(" })"); - QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->current; + QV4::ExecutionContext *ctx = QV8Engine::getV4(engine)->currentContext(); QV4::Scope scope(ctx); QV4::Script program(QV8Engine::getV4(engine)->rootContext, functionSource); @@ -6060,6 +6061,13 @@ void tst_qqmlecmascript::signalHandlers() QMetaObject::invokeMethod(o, "testSignalHandlerDefined"); QCOMPARE(o->property("definedHandlerResult").toBool(), true); + QVariant result; + QMetaObject::invokeMethod(o, "testConnectionOnAlias", Q_RETURN_ARG(QVariant, result)); + QCOMPARE(result.toBool(), true); + + QMetaObject::invokeMethod(o, "testAliasSignalHandler", Q_RETURN_ARG(QVariant, result)); + QCOMPARE(result.toBool(), true); + delete o; } @@ -7491,6 +7499,14 @@ void tst_qqmlecmascript::qtbug_34792() delete object; } +void tst_qqmlecmascript::noCaptureWhenWritingProperty() +{ + QQmlComponent component(&engine, testFileUrl("noCaptureWhenWritingProperty.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("somePropertyEvaluated").toBool(), false); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmllanguage/data/customParserBindingScopes.qml b/tests/auto/qml/qqmllanguage/data/customParserBindingScopes.qml new file mode 100644 index 0000000000..2efc199f32 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/customParserBindingScopes.qml @@ -0,0 +1,19 @@ +import Test 1.0 +import QtQml 2.0 +QtObject { + id: root + + property int otherProperty: 10 + + property QtObject child: QtObject { + id: child + + property int testProperty; + property int otherProperty: 41 + + property QtObject customBinder: CustomBinding { + target: child + testProperty: otherProperty + 1 + } + } +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 3957f9d872..4a4ab3b81a 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -89,6 +89,8 @@ void registerTypes() qmlRegisterUncreatableType<MyUncreateableBaseClass,1>("Test", 1, 1, "MyUncreateableBaseClass", "Cannot create MyUncreateableBaseClass"); qmlRegisterType<MyCreateableDerivedClass,1>("Test", 1, 1, "MyCreateableDerivedClass"); + + qmlRegisterCustomType<CustomBinding>("Test", 1, 0, "CustomBinding", new CustomBindingParser); } QVariant myCustomVariantTypeConverter(const QString &data) @@ -97,3 +99,61 @@ QVariant myCustomVariantTypeConverter(const QString &data) rv.a = data.toInt(); return QVariant::fromValue(rv); } + + +QByteArray CustomBindingParser::compile(const QList<QQmlCustomParserProperty> &properties) +{ + QByteArray result; + QDataStream ds(&result, QIODevice::WriteOnly); + + ds << properties.count(); + for (int i = 0; i < properties.count(); ++i) { + const QQmlCustomParserProperty &prop = properties.at(i); + ds << prop.name(); + + Q_ASSERT(prop.assignedValues().count() == 1); + QVariant value = prop.assignedValues().first(); + + Q_ASSERT(value.userType() == qMetaTypeId<QQmlScript::Variant>()); + QQmlScript::Variant v = qvariant_cast<QQmlScript::Variant>(value); + Q_ASSERT(v.type() == QQmlScript::Variant::Script); + int bindingId = bindingIdentifier(v, prop.name()); + ds << bindingId; + + ds << prop.location().line; + } + + return result; +} + +void CustomBindingParser::setCustomData(QObject *object, const QByteArray &data) +{ + CustomBinding *customBinding = qobject_cast<CustomBinding*>(object); + Q_ASSERT(customBinding); + customBinding->m_bindingData = data; +} + +void CustomBinding::componentComplete() +{ + Q_ASSERT(m_target); + + QDataStream ds(m_bindingData); + int count; + ds >> count; + for (int i = 0; i < count; ++i) { + QString name; + ds >> name; + + int bindingId; + ds >> bindingId; + + int line; + ds >> line; + + QQmlBinding *binding = QQmlBinding::createBinding(QQmlBinding::Identifier(bindingId), m_target, qmlContext(this), QString(), line); + + QQmlProperty property(m_target, name, qmlContext(this)); + binding->setTarget(property); + QQmlPropertyPrivate::setBinding(property, binding); + } +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 703b26a73c..a968d9a25a 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1070,6 +1070,29 @@ QML_DECLARE_TYPE(MyRevisionedSubclass) QML_DECLARE_TYPE(MySubclass) QML_DECLARE_TYPE(MyReceiversTestObject) +class CustomBinding : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QObject* target READ target WRITE setTarget) +public: + + virtual void classBegin() {} + virtual void componentComplete(); + + QObject *target() const { return m_target; } + void setTarget(QObject *newTarget) { m_target = newTarget; } + + QPointer<QObject> m_target; + QByteArray m_bindingData; +}; + +class CustomBindingParser : public QQmlCustomParser +{ + virtual QByteArray compile(const QList<QQmlCustomParserProperty> &properties); + virtual void setCustomData(QObject *object, const QByteArray &data); +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 621061ab6a..6a577ec91c 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -214,6 +214,8 @@ private slots: void compositeSingletonSelectors(); void compositeSingletonRegistered(); + void customParserBindingScopes(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -3534,6 +3536,17 @@ void tst_qqmllanguage::compositeSingletonRegistered() verifyCompositeSingletonPropertyValues(o, "value1", 925, "value2", 755); } +void tst_qqmllanguage::customParserBindingScopes() +{ + QQmlComponent component(&engine, testFile("customParserBindingScopes.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + QPointer<QObject> child = qvariant_cast<QObject*>(o->property("child")); + QVERIFY(!child.isNull()); + QCOMPARE(child->property("testProperty").toInt(), 42); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp index ca212d333b..17f54508a3 100644 --- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp +++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp @@ -55,6 +55,8 @@ public: tst_QQmlPropertyMap() {} private slots: + void initTestCase(); + void insert(); void operatorInsert(); void operatorValue(); @@ -68,8 +70,39 @@ private slots: void metaObjectAccessibility(); void QTBUG_31226(); void QTBUG_29836(); + void QTBUG_35233(); + void disallowExtending(); +}; + +class LazyPropertyMap : public QQmlPropertyMap, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + + Q_PROPERTY(int someFixedProperty READ someFixedProperty WRITE setSomeFixedProperty) +public: + LazyPropertyMap() + : QQmlPropertyMap(this, /*parent*/0) + , value(0) + {} + + virtual void classBegin() {} + virtual void componentComplete() { + insert(QStringLiteral("lateProperty"), QStringLiteral("lateValue")); + } + + int someFixedProperty() const { return value; } + void setSomeFixedProperty(int v) { value = v; } + +private: + int value; }; +void tst_QQmlPropertyMap::initTestCase() +{ + qmlRegisterType<LazyPropertyMap>("QTBUG_35233", 1, 0, "LazyPropertyMap"); +} + void tst_QQmlPropertyMap::insert() { QQmlPropertyMap map; @@ -369,6 +402,54 @@ void tst_QQmlPropertyMap::QTBUG_29836() } +void tst_QQmlPropertyMap::QTBUG_35233() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQml 2.0\n" + "import QTBUG_35233 1.0\n" + "QtObject {\n" + " property QtObject testMap: LazyPropertyMap {\n" + " id: map\n" + " }\n" + " property QtObject sibling: QtObject {\n" + " objectName: \"sibling\"\n" + " property string testValue: map.lateProperty\n" + " }\n" + "}", QUrl()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + + QObject *sibling = obj->findChild<QObject*>("sibling"); + QVERIFY(sibling); + QCOMPARE(sibling->property("testValue").toString(), QString("lateValue")); +} + +void tst_QQmlPropertyMap::disallowExtending() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQml 2.0\n" + "import QTBUG_35233 1.0\n" + "LazyPropertyMap {\n" + " id: blah\n" + " someFixedProperty: 42\n" + "}\n", QUrl()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + + component.setData("import QtQml 2.0\n" + "import QTBUG_35233 1.0\n" + "LazyPropertyMap {\n" + " id: blah\n" + " property int someNewProperty;\n" + "}\n", QUrl()); + obj.reset(component.create()); + QVERIFY(obj.isNull()); + QCOMPARE(component.errors().count(), 1); + QCOMPARE(component.errors().at(0).toString(), QStringLiteral("<Unknown File>: Fully dynamic types cannot declare new properties.")); +} + QTEST_MAIN(tst_QQmlPropertyMap) #include "tst_qqmlpropertymap.moc" diff --git a/tests/auto/qml/qqmltranslation/data/jstranslation.qml b/tests/auto/qml/qqmltranslation/data/jstranslation.qml new file mode 100644 index 0000000000..7adde019fa --- /dev/null +++ b/tests/auto/qml/qqmltranslation/data/jstranslation.qml @@ -0,0 +1,20 @@ +import QtQuick 2.0 +import "translation.js" as Js + +QtObject { + property string basic: Js.basic() + property string basic2: Js.basic2() + property string basic3: Js.basic3() + + property string disambiguation: Js.disambiguation() + property string disambiguation2: Js.disambiguation2() + property string disambiguation3: Js.disambiguation3() + + property string noop: Js.noop() + property string noop2: Js.noop2() + + property string singular: Js.singular() + property string singular2: Js.singular2() + property string plural: Js.plural() + property string plural2: Js.plural2() +} diff --git a/tests/auto/qml/qqmltranslation/data/translation.js b/tests/auto/qml/qqmltranslation/data/translation.js new file mode 100644 index 0000000000..c1e25dcd2f --- /dev/null +++ b/tests/auto/qml/qqmltranslation/data/translation.js @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +function basic() { + return qsTr("hello") +} + +function basic2() { + return qsTranslate("CustomContext", "goodbye") +} + +function basic3() { + if (1) + return qsTr("hello") + return ""; +} + +function disambiguation() { + return qsTr("hi", "informal 'hello'") +} + +function disambiguation2() { + return qsTranslate("CustomContext", "see ya", "informal 'goodbye'") +} + +function disambiguation3() { + if (1) + return qsTr("hi", "informal 'hello'") + return ""; +} + +function noop() { + var _noop = QT_TR_NOOP("hello") + return qsTr(_noop) +} + +function noop2() { + var _noop2 = QT_TRANSLATE_NOOP("CustomContext", "goodbye") + return qsTranslate("CustomContext", _noop2) +} + +function singular() { + return qsTr("%n duck(s)", "", 1) +} + +function singular2() { + if (1) + return qsTr("%n duck(s)", "", 1) + return ""; +} + +function plural() { + return qsTr("%n duck(s)", "", 2) +} + +function plural2() { + if (1) + return qsTr("%n duck(s)", "", 2) + return ""; +} diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp index 0e22d3cfca..01e1cf85fb 100644 --- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp +++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp @@ -52,19 +52,32 @@ public: tst_qqmltranslation() {} private slots: + void translation_data(); void translation(); void idTranslation(); - void translationInQrc(); }; +void tst_qqmltranslation::translation_data() +{ + QTest::addColumn<QString>("translation"); + QTest::addColumn<QUrl>("testFile"); + + QTest::newRow("qml") << QStringLiteral("qml_fr") << testFileUrl("translation.qml"); + QTest::newRow("qrc") << QStringLiteral(":/qml_fr.qm") << QUrl("qrc:/translation.qml"); + QTest::newRow("js") << QStringLiteral("qml_fr") << testFileUrl("jstranslation.qml"); +} + void tst_qqmltranslation::translation() { + QFETCH(QString, translation); + QFETCH(QUrl, testFile); + QTranslator translator; - translator.load(QLatin1String("qml_fr"), dataDirectory()); + translator.load(translation, dataDirectory()); QCoreApplication::installTranslator(&translator); QQmlEngine engine; - QQmlComponent component(&engine, testFileUrl("translation.qml")); + QQmlComponent component(&engine, testFile); QObject *object = component.create(); QVERIFY(object != 0); @@ -104,34 +117,6 @@ void tst_qqmltranslation::idTranslation() delete object; } -void tst_qqmltranslation::translationInQrc() -{ - QTranslator translator; - translator.load(":/qml_fr.qm"); - QCoreApplication::installTranslator(&translator); - - QQmlEngine engine; - QQmlComponent component(&engine, QUrl("qrc:/translation.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); - - QCOMPARE(object->property("basic").toString(), QLatin1String("bonjour")); - QCOMPARE(object->property("basic2").toString(), QLatin1String("au revoir")); - QCOMPARE(object->property("basic3").toString(), QLatin1String("bonjour")); - QCOMPARE(object->property("disambiguation").toString(), QLatin1String("salut")); - QCOMPARE(object->property("disambiguation2").toString(), QString::fromUtf8("\xc3\xa0 plus tard")); - QCOMPARE(object->property("disambiguation3").toString(), QLatin1String("salut")); - QCOMPARE(object->property("noop").toString(), QLatin1String("bonjour")); - QCOMPARE(object->property("noop2").toString(), QLatin1String("au revoir")); - QCOMPARE(object->property("singular").toString(), QLatin1String("1 canard")); - QCOMPARE(object->property("singular2").toString(), QLatin1String("1 canard")); - QCOMPARE(object->property("plural").toString(), QLatin1String("2 canards")); - QCOMPARE(object->property("plural2").toString(), QLatin1String("2 canards")); - - QCoreApplication::removeTranslator(&translator); - delete object; -} - QTEST_MAIN(tst_qqmltranslation) #include "tst_qqmltranslation.moc" diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp index 3ae27fe9c3..9c67e6e2e9 100644 --- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp +++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp @@ -127,8 +127,8 @@ private: void tst_qqmlxmlhttprequest::domExceptionCodes() { QQmlComponent component(&engine, testFileUrl("domExceptionCodes.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("index_size_err").toInt(), 1); QCOMPARE(object->property("domstring_size_err").toInt(), 2); @@ -147,8 +147,6 @@ void tst_qqmlxmlhttprequest::domExceptionCodes() QCOMPARE(object->property("invalid_access_err").toInt(), 15); QCOMPARE(object->property("validation_err").toInt(), 16); QCOMPARE(object->property("type_mismatch_err").toInt(), 17); - - delete object; } void tst_qqmlxmlhttprequest::callbackException_data() @@ -172,15 +170,13 @@ void tst_qqmlxmlhttprequest::callbackException() QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); QQmlComponent component(&engine, testFileUrl("callbackException.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "testdocument.html"); object->setProperty("which", which); component.completeCreate(); QTRY_VERIFY(object->property("threw").toBool() == true); - - delete object; } // Test that the state value properties on the XMLHttpRequest constructor have the correct values. @@ -188,61 +184,53 @@ void tst_qqmlxmlhttprequest::callbackException() void tst_qqmlxmlhttprequest::staticStateValues() { QQmlComponent component(&engine, testFileUrl("staticStateValues.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("unsent").toInt(), 0); QCOMPARE(object->property("opened").toInt(), 1); QCOMPARE(object->property("headers_received").toInt(), 2); QCOMPARE(object->property("loading").toInt(), 3); QCOMPARE(object->property("done").toInt(), 4); - - delete object; } // Test that the state value properties on instances have the correct values. void tst_qqmlxmlhttprequest::instanceStateValues() { QQmlComponent component(&engine, testFileUrl("instanceStateValues.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("unsent").toInt(), 0); QCOMPARE(object->property("opened").toInt(), 1); QCOMPARE(object->property("headers_received").toInt(), 2); QCOMPARE(object->property("loading").toInt(), 3); QCOMPARE(object->property("done").toInt(), 4); - - delete object; } // Test calling constructor void tst_qqmlxmlhttprequest::constructor() { QQmlComponent component(&engine, testFileUrl("constructor.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("calledAsConstructor").toBool(), true); QCOMPARE(object->property("calledAsFunction").toBool(), true); - - delete object; } // Test that all the properties are set correctly before any request is sent void tst_qqmlxmlhttprequest::defaultState() { QQmlComponent component(&engine, testFileUrl("defaultState.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("readState").toInt(), 0); QCOMPARE(object->property("statusIsException").toBool(), true); QCOMPARE(object->property("statusTextIsException").toBool(), true); QCOMPARE(object->property("responseText").toString(), QString()); QCOMPARE(object->property("responseXMLIsNull").toBool(), true); - - delete object; } // Test valid XMLHttpRequest.open() calls @@ -262,8 +250,8 @@ void tst_qqmlxmlhttprequest::open() } QQmlComponent component(&engine, qmlFile); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", url); component.completeCreate(); @@ -275,8 +263,6 @@ void tst_qqmlxmlhttprequest::open() QCOMPARE(object->property("responseXML").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } void tst_qqmlxmlhttprequest::open_data() @@ -297,24 +283,20 @@ void tst_qqmlxmlhttprequest::open_data() void tst_qqmlxmlhttprequest::open_invalid_method() { QQmlComponent component(&engine, testFileUrl("open_invalid_method.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("exceptionThrown").toBool(), true); - - delete object; } // Test that calling XMLHttpRequest.open() with sync raises an exception void tst_qqmlxmlhttprequest::open_sync() { QQmlComponent component(&engine, testFileUrl("open_sync.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("exceptionThrown").toBool(), true); - - delete object; } // Calling with incorrect arg count raises an exception @@ -322,22 +304,18 @@ void tst_qqmlxmlhttprequest::open_arg_count() { { QQmlComponent component(&engine, testFileUrl("open_arg_count.1.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("exceptionThrown").toBool(), true); - - delete object; } { QQmlComponent component(&engine, testFileUrl("open_arg_count.2.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("exceptionThrown").toBool(), true); - - delete object; } } @@ -351,14 +329,12 @@ void tst_qqmlxmlhttprequest::setRequestHeader() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("setRequestHeader.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Test valid setRequestHeader() calls with different header cases @@ -371,25 +347,21 @@ void tst_qqmlxmlhttprequest::setRequestHeader_caseInsensitive() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("setRequestHeader_caseInsensitive.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Test setting headers before open() throws exception void tst_qqmlxmlhttprequest::setRequestHeader_unsent() { QQmlComponent component(&engine, testFileUrl("setRequestHeader_unsent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); - - delete object; } void tst_qqmlxmlhttprequest::setRequestHeader_illegalName_data() @@ -432,8 +404,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("setRequestHeader_illegalName.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); object->setProperty("header", name); component.completeCreate(); @@ -446,8 +418,6 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName() QCOMPARE(object->property("responseXML").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Test that attempting to set a header after a request is sent throws an exception @@ -460,53 +430,45 @@ void tst_qqmlxmlhttprequest::setRequestHeader_sent() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("setRequestHeader_sent.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QCOMPARE(object->property("test").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Invalid arg count throws exception void tst_qqmlxmlhttprequest::setRequestHeader_args() { QQmlComponent component(&engine, testFileUrl("setRequestHeader_args.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("exceptionThrown").toBool(), true); - - delete object; } // Test that calling send() in UNSENT state throws an exception void tst_qqmlxmlhttprequest::send_unsent() { QQmlComponent component(&engine, testFileUrl("send_unsent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); - - delete object; } // Test attempting to resend a sent request throws an exception void tst_qqmlxmlhttprequest::send_alreadySent() { QQmlComponent component(&engine, testFileUrl("send_alreadySent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Test that sends for GET, HEAD and DELETE ignore data @@ -520,15 +482,13 @@ void tst_qqmlxmlhttprequest::send_ignoreData() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("send_ignoreData.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("reqType", "GET"); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } { @@ -539,15 +499,13 @@ void tst_qqmlxmlhttprequest::send_ignoreData() QUrl())); QQmlComponent component(&engine, testFileUrl("send_ignoreData.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("reqType", "HEAD"); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } { @@ -558,15 +516,13 @@ void tst_qqmlxmlhttprequest::send_ignoreData() QUrl())); QQmlComponent component(&engine, testFileUrl("send_ignoreData.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("reqType", "DELETE"); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } } @@ -583,14 +539,12 @@ void tst_qqmlxmlhttprequest::send_withdata() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl(file_qml)); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } void tst_qqmlxmlhttprequest::send_withdata_data() @@ -611,8 +565,8 @@ void tst_qqmlxmlhttprequest::send_withdata_data() void tst_qqmlxmlhttprequest::abort_unsent() { QQmlComponent component(&engine, testFileUrl("abort_unsent.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "testdocument.html"); component.completeCreate(); @@ -624,16 +578,14 @@ void tst_qqmlxmlhttprequest::abort_unsent() QCOMPARE(object->property("responseXML").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Test abort() cancels an open (but unsent) request void tst_qqmlxmlhttprequest::abort_opened() { QQmlComponent component(&engine, testFileUrl("abort_opened.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "testdocument.html"); component.completeCreate(); @@ -645,8 +597,6 @@ void tst_qqmlxmlhttprequest::abort_opened() QCOMPARE(object->property("responseXML").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } // Test abort() aborts in progress send @@ -659,8 +609,8 @@ void tst_qqmlxmlhttprequest::abort() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("abort.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("urlDummy", "http://127.0.0.1:14449/testdocument.html"); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); @@ -670,8 +620,6 @@ void tst_qqmlxmlhttprequest::abort() QCOMPARE(object->property("endStateUnsent").toBool(), true); QTRY_VERIFY(object->property("dataOK").toBool() == true); - - delete object; } void tst_qqmlxmlhttprequest::getResponseHeader() @@ -686,8 +634,8 @@ void tst_qqmlxmlhttprequest::getResponseHeader() QQmlComponent component(&engine, testFileUrl("getResponseHeader.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); @@ -709,44 +657,36 @@ void tst_qqmlxmlhttprequest::getResponseHeader() QCOMPARE(object->property("doneValidHeader").toBool(), true); QCOMPARE(object->property("doneMultiValidHeader").toBool(), true); QCOMPARE(object->property("doneCookieHeader").toBool(), true); - - delete object; } // Test getResponseHeader throws an exception in an invalid state void tst_qqmlxmlhttprequest::getResponseHeader_unsent() { QQmlComponent component(&engine, testFileUrl("getResponseHeader_unsent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); - - delete object; } // Test getResponseHeader throws an exception in an invalid state void tst_qqmlxmlhttprequest::getResponseHeader_sent() { QQmlComponent component(&engine, testFileUrl("getResponseHeader_sent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); - - delete object; } // Invalid arg count throws exception void tst_qqmlxmlhttprequest::getResponseHeader_args() { QQmlComponent component(&engine, testFileUrl("getResponseHeader_args.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("exceptionThrown").toBool() == true); - - delete object; } void tst_qqmlxmlhttprequest::getAllResponseHeaders() @@ -760,8 +700,8 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); component.completeCreate(); @@ -777,44 +717,36 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders() QCOMPARE(object->property("doneState").toBool(), true); QCOMPARE(object->property("doneHeader").toBool(), true); - - delete object; } // Test getAllResponseHeaders throws an exception in an invalid state void tst_qqmlxmlhttprequest::getAllResponseHeaders_unsent() { QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders_unsent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); - - delete object; } // Test getAllResponseHeaders throws an exception in an invalid state void tst_qqmlxmlhttprequest::getAllResponseHeaders_sent() { QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders_sent.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("test").toBool(), true); - - delete object; } // Invalid arg count throws exception void tst_qqmlxmlhttprequest::getAllResponseHeaders_args() { QQmlComponent component(&engine, testFileUrl("getAllResponseHeaders_args.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("exceptionThrown").toBool() == true); - - delete object; } void tst_qqmlxmlhttprequest::status() @@ -829,8 +761,8 @@ void tst_qqmlxmlhttprequest::status() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("status.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); object->setProperty("expectedStatus", status); component.completeCreate(); @@ -844,8 +776,6 @@ void tst_qqmlxmlhttprequest::status() QCOMPARE(object->property("loading").toBool(), true); QCOMPARE(object->property("done").toBool(), true); QCOMPARE(object->property("resetException").toBool(), true); - - delete object; } void tst_qqmlxmlhttprequest::status_data() @@ -870,8 +800,8 @@ void tst_qqmlxmlhttprequest::statusText() testFileUrl("testdocument.html"))); QQmlComponent component(&engine, testFileUrl("statusText.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); object->setProperty("expectedStatus", statusText); component.completeCreate(); @@ -885,8 +815,6 @@ void tst_qqmlxmlhttprequest::statusText() QCOMPARE(object->property("loading").toBool(), true); QCOMPARE(object->property("done").toBool(), true); QCOMPARE(object->property("resetException").toBool(), true); - - delete object; } void tst_qqmlxmlhttprequest::statusText_data() @@ -912,8 +840,8 @@ void tst_qqmlxmlhttprequest::responseText() bodyUrl)); QQmlComponent component(&engine, testFileUrl("responseText.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/testdocument.html"); object->setProperty("expectedText", responseText); component.completeCreate(); @@ -927,8 +855,6 @@ void tst_qqmlxmlhttprequest::responseText() QCOMPARE(object->property("loading").toBool(), true); QCOMPARE(object->property("done").toBool(), true); QCOMPARE(object->property("reset").toBool(), true); - - delete object; } void tst_qqmlxmlhttprequest::responseText_data() @@ -950,11 +876,11 @@ void tst_qqmlxmlhttprequest::nonUtf8() QFETCH(QString, xmlRootNodeValue); QQmlComponent component(&engine, testFileUrl("utf16.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); object->setProperty("fileName", fileName); - QMetaObject::invokeMethod(object, "startRequest"); + QMetaObject::invokeMethod(object.data(), "startRequest"); QTRY_VERIFY(object->property("dataOK").toBool() == true); @@ -964,8 +890,6 @@ void tst_qqmlxmlhttprequest::nonUtf8() QString rootNodeValue = object->property("responseXmlRootNodeValue").toString(); QCOMPARE(rootNodeValue, xmlRootNodeValue); } - - delete object; } void tst_qqmlxmlhttprequest::nonUtf8_data() @@ -989,8 +913,8 @@ void tst_qqmlxmlhttprequest::nonUtf8_data() void tst_qqmlxmlhttprequest::invalidMethodUsage() { QQmlComponent component(&engine, testFileUrl("invalidMethodUsage.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QCOMPARE(object->property("readyState").toBool(), true); QCOMPARE(object->property("status").toBool(), true); @@ -1004,8 +928,6 @@ void tst_qqmlxmlhttprequest::invalidMethodUsage() QCOMPARE(object->property("abort").toBool(), true); QCOMPARE(object->property("getResponseHeader").toBool(), true); QCOMPARE(object->property("getAllResponseHeaders").toBool(), true); - - delete object; } // Test that XMLHttpRequest transparently redirects @@ -1018,16 +940,14 @@ void tst_qqmlxmlhttprequest::redirects() server.serveDirectory(dataDirectory()); QQmlComponent component(&engine, testFileUrl("redirects.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/redirect.html"); object->setProperty("expectedText", ""); component.completeCreate(); QTRY_VERIFY(object->property("done").toBool() == true); QCOMPARE(object->property("dataOK").toBool(), true); - - delete object; } { @@ -1037,16 +957,14 @@ void tst_qqmlxmlhttprequest::redirects() server.serveDirectory(dataDirectory()); QQmlComponent component(&engine, testFileUrl("redirectError.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/redirect.html"); object->setProperty("expectedText", ""); component.completeCreate(); QTRY_VERIFY(object->property("done").toBool() == true); QCOMPARE(object->property("dataOK").toBool(), true); - - delete object; } { @@ -1056,8 +974,8 @@ void tst_qqmlxmlhttprequest::redirects() server.serveDirectory(dataDirectory()); QQmlComponent component(&engine, testFileUrl("redirectRecur.qml")); - QObject *object = component.beginCreate(engine.rootContext()); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); object->setProperty("url", "http://127.0.0.1:14445/redirect.html"); object->setProperty("expectedText", ""); component.completeCreate(); @@ -1069,92 +987,78 @@ void tst_qqmlxmlhttprequest::redirects() QVERIFY(object->property("done").toBool() == true); QCOMPARE(object->property("dataOK").toBool(), true); - - delete object; } } void tst_qqmlxmlhttprequest::responseXML_invalid() { QQmlComponent component(&engine, testFileUrl("responseXML_invalid.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("dataOK").toBool() == true); QCOMPARE(object->property("xmlNull").toBool(), true); - - delete object; } // Test the Document DOM element void tst_qqmlxmlhttprequest::document() { QQmlComponent component(&engine, testFileUrl("document.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("dataOK").toBool() == true); QCOMPARE(object->property("xmlTest").toBool(), true); - - delete object; } // Test the Element DOM element void tst_qqmlxmlhttprequest::element() { QQmlComponent component(&engine, testFileUrl("element.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("dataOK").toBool() == true); QCOMPARE(object->property("xmlTest").toBool(), true); - - delete object; } // Test the Attr DOM element void tst_qqmlxmlhttprequest::attr() { QQmlComponent component(&engine, testFileUrl("attr.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("dataOK").toBool() == true); QCOMPARE(object->property("xmlTest").toBool(), true); - - delete object; } // Test the Text DOM element void tst_qqmlxmlhttprequest::text() { QQmlComponent component(&engine, testFileUrl("text.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("dataOK").toBool() == true); QCOMPARE(object->property("xmlTest").toBool(), true); - - delete object; } // Test the CDataSection DOM element void tst_qqmlxmlhttprequest::cdata() { QQmlComponent component(&engine, testFileUrl("cdata.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); QTRY_VERIFY(object->property("dataOK").toBool() == true); QCOMPARE(object->property("xmlTest").toBool(), true); - - delete object; } void tst_qqmlxmlhttprequest::stateChangeCallingContext() @@ -1171,11 +1075,10 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext() server.serveDirectory(dataDirectory(), TestHTTPServer::Delay); QQmlComponent component(&engine, testFileUrl("stateChangeCallingContext.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); server.sendDelayedItem(); QTRY_VERIFY(object->property("success").toBool() == true); - delete object; } QTEST_MAIN(tst_qqmlxmlhttprequest) diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp index ef27445920..dfcef43a7e 100644 --- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp +++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp @@ -184,7 +184,6 @@ void tst_qquickapplication::layoutDirection() // mirrored QGuiApplication::setLayoutDirection(Qt::RightToLeft); - QEXPECT_FAIL("", "QTBUG-21573", Abort); QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::RightToLeft); // not mirrored again diff --git a/tests/auto/quick/qquickflickable/data/stopAtBounds.qml b/tests/auto/quick/qquickflickable/data/stopAtBounds.qml new file mode 100644 index 0000000000..d8661f3e45 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/stopAtBounds.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 + +Flickable { + id: outer + objectName: "flickable" + width: 400 + height: 400 + contentX: 50 + contentY: 50 + contentWidth: 500 + contentHeight: 500 + boundsBehavior: Flickable.StopAtBounds + + Rectangle { + x: 100 + y: 100 + width: 300 + height: 300 + + color: "yellow" + } +} diff --git a/tests/auto/quick/qquickflickable/qquickflickable.pro b/tests/auto/quick/qquickflickable/qquickflickable.pro index dfc8d7541b..88dc2fbc2a 100644 --- a/tests/auto/quick/qquickflickable/qquickflickable.pro +++ b/tests/auto/quick/qquickflickable/qquickflickable.pro @@ -11,4 +11,3 @@ TESTDATA = data/* QT += core-private gui-private qml-private quick-private testlib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -CONFIG+=insignificant_test diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 3c518c509b..794f9a8af6 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -94,6 +94,8 @@ private slots: void flickTwiceUsingTouches(); void nestedStopAtBounds(); void nestedStopAtBounds_data(); + void stopAtBounds(); + void stopAtBounds_data(); void nestedMouseAreaUsingTouch(); private: @@ -285,11 +287,6 @@ void tst_qquickflickable::rebound() window->rootObject()->setProperty("transitionsStarted", 0); window->rootObject()->setProperty("transitionsFinished", 0); -#ifdef Q_OS_MAC - QSKIP("QTBUG-26696 - sometimes fails on Mac"); - return; -#endif - // flick and trigger the transition multiple times // (moving signals are emitted as soon as the first transition starts) flick(window.data(), QPoint(20,20), QPoint(120,120), 200); // both x and y will bounce back @@ -425,8 +422,7 @@ void tst_qquickflickable::pressDelay() // As we moved pass the drag threshold, we should never receive the press QVERIFY(mouseArea->property("pressed").toBool() == false); - QTest::qWait(200); - QVERIFY(mouseArea->property("pressed").toBool() == false); + QTRY_VERIFY(mouseArea->property("pressed").toBool() == false); // On release the clicked signal should *not* be emitted QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 190)); @@ -1180,8 +1176,7 @@ void tst_qquickflickable::margins() // position to the far right, including margin obj->setContentX(1600 + 50 - obj->width()); obj->returnToBounds(); - QTest::qWait(200); - QCOMPARE(obj->contentX(), 1600. + 50. - obj->width()); + QTRY_COMPARE(obj->contentX(), 1600. + 50. - obj->width()); // position beyond the far right, including margin obj->setContentX(1600 + 50 - obj->width() + 1.); @@ -1196,8 +1191,7 @@ void tst_qquickflickable::margins() // position to the far bottom, including margin obj->setContentY(600 + 30 - obj->height()); obj->returnToBounds(); - QTest::qWait(200); - QCOMPARE(obj->contentY(), 600. + 30. - obj->height()); + QTRY_COMPARE(obj->contentY(), 600. + 30. - obj->height()); // position beyond the far bottom, including margin obj->setContentY(600 + 30 - obj->height() + 1.); @@ -1266,14 +1260,12 @@ void tst_qquickflickable::clickAndDragWhenTransformed() // click outside child rect QTest::mousePress(view.data(), Qt::LeftButton, 0, QPoint(190, 190)); - QTest::qWait(10); - QCOMPARE(flickable->property("itemPressed").toBool(), false); + QTRY_COMPARE(flickable->property("itemPressed").toBool(), false); QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(190, 190)); // click inside child rect QTest::mousePress(view.data(), Qt::LeftButton, 0, QPoint(200, 200)); - QTest::qWait(10); - QCOMPARE(flickable->property("itemPressed").toBool(), true); + QTRY_COMPARE(flickable->property("itemPressed").toBool(), true); QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(200, 200)); const int threshold = qApp->styleHints()->startDragDistance(); @@ -1322,13 +1314,15 @@ void tst_qquickflickable::flickTwiceUsingTouches() qreal contentYAfterFirstFlick = flickable->contentY(); qDebug() << "contentYAfterFirstFlick " << contentYAfterFirstFlick; QVERIFY(contentYAfterFirstFlick > 50.0f); + // Wait until view stops moving + QTRY_VERIFY(!flickable->isMoving()); flickWithTouch(window.data(), touchDevice, QPoint(100, 400), QPoint(100, 240)); // In the original bug, that second flick would cause Flickable to halt immediately qreal contentYAfterSecondFlick = flickable->contentY(); qDebug() << "contentYAfterSecondFlick " << contentYAfterSecondFlick; - QVERIFY(contentYAfterSecondFlick > (contentYAfterFirstFlick + 80.0f)); + QTRY_VERIFY(contentYAfterSecondFlick > (contentYAfterFirstFlick + 80.0f)); } void tst_qquickflickable::flickWithTouch(QWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to) @@ -1419,6 +1413,90 @@ void tst_qquickflickable::nestedStopAtBounds() QTRY_VERIFY(!outer->isMoving()); } +void tst_qquickflickable::stopAtBounds_data() +{ + QTest::addColumn<bool>("transpose"); + QTest::addColumn<bool>("invert"); + + QTest::newRow("left") << false << false; + QTest::newRow("right") << false << true; + QTest::newRow("top") << true << false; + QTest::newRow("bottom") << true << true; +} + +void tst_qquickflickable::stopAtBounds() +{ + QFETCH(bool, transpose); + QFETCH(bool, invert); + + QQuickView view; + view.setSource(testFileUrl("stopAtBounds.qml")); + QTRY_COMPARE(view.status(), QQuickView::Ready); + QQuickViewTestUtil::centerOnScreen(&view); + QQuickViewTestUtil::moveMouseAway(&view); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QVERIFY(view.rootObject()); + + QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(view.rootObject()); + QVERIFY(flickable); + + if (transpose) + flickable->setContentY(invert ? 100 : 0); + else + flickable->setContentX(invert ? 100 : 0); + + const int threshold = qApp->styleHints()->startDragDistance(); + + QPoint position(200, 200); + int &axis = transpose ? position.ry() : position.rx(); + + // drag away from the aligned boundary. View should not move + QTest::mousePress(&view, Qt::LeftButton, 0, position); + QTest::qWait(10); + for (int i = 0; i < 3; ++i) { + axis += invert ? -threshold : threshold; + QTest::mouseMove(&view, position); + } + QCOMPARE(flickable->isDragging(), false); + if (invert) + QCOMPARE(transpose ? flickable->isAtYEnd() : flickable->isAtXEnd(), true); + else + QCOMPARE(transpose ? flickable->isAtYBeginning() : flickable->isAtXBeginning(), true); + + // drag back towards boundary + for (int i = 0; i < 24; ++i) { + axis += invert ? threshold / 3 : -threshold / 3; + QTest::mouseMove(&view, position); + } + QTRY_COMPARE(flickable->isDragging(), true); + if (invert) + QCOMPARE(transpose ? flickable->isAtYEnd() : flickable->isAtXEnd(), false); + else + QCOMPARE(transpose ? flickable->isAtYBeginning() : flickable->isAtXBeginning(), false); + + // Drag away from the aligned boundary again. + // None of the mouse movements will position the view at the boundary exactly, + // but the view should end up aligned on the boundary + for (int i = 0; i < 5; ++i) { + axis += invert ? -threshold * 2 : threshold * 2; + QTest::mouseMove(&view, position); + } + QCOMPARE(flickable->isDragging(), true); + + // we should have hit the boundary and stopped + if (invert) { + QCOMPARE(transpose ? flickable->isAtYEnd() : flickable->isAtXEnd(), true); + QCOMPARE(transpose ? flickable->contentY() : flickable->contentX(), 100.0); + } else { + QCOMPARE(transpose ? flickable->isAtYBeginning() : flickable->isAtXBeginning(), true); + QCOMPARE(transpose ? flickable->contentY() : flickable->contentX(), 0.0); + } + + QTest::mouseRelease(&view, Qt::LeftButton, 0, position); +} + void tst_qquickflickable::nestedMouseAreaUsingTouch() { QTouchDevice *touchDevice = new QTouchDevice; diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 97e002361b..2c6dcd72ba 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -44,7 +44,6 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickwindow.h> #include <QtQuick/qquickview.h> -#include <QtWidgets/QGraphicsSceneMouseEvent> #include "private/qquickfocusscope_p.h" #include "private/qquickitem_p.h" #include <qpa/qwindowsysteminterface.h> @@ -1151,6 +1150,30 @@ void tst_qquickitem::enabledFocus() QCOMPARE(child2.hasFocus(), false); QCOMPARE(child2.hasActiveFocus(), false); QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&child1)); + + child2.setFocus(true); + QCOMPARE(root.isEnabled(), true); + QCOMPARE(root.hasFocus(), true); + QCOMPARE(root.hasActiveFocus(), true); + QCOMPARE(child1.isEnabled(), true); + QCOMPARE(child1.hasFocus(), false); + QCOMPARE(child1.hasActiveFocus(), false); + QCOMPARE(child2.isEnabled(), false); + QCOMPARE(child2.hasFocus(), true); + QCOMPARE(child2.hasActiveFocus(), false); + QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); + + root.setEnabled(false); + QCOMPARE(root.isEnabled(), false); + QCOMPARE(root.hasFocus(), true); + QCOMPARE(root.hasActiveFocus(), false); + QCOMPARE(child1.isEnabled(), false); + QCOMPARE(child1.hasFocus(), false); + QCOMPARE(child1.hasActiveFocus(), false); + QCOMPARE(child2.isEnabled(), false); + QCOMPARE(child2.hasFocus(), true); + QCOMPARE(child2.hasActiveFocus(), false); + QCOMPARE(window.activeFocusItem(), window.contentItem()); } static inline QByteArray msgItem(const QQuickItem *item) diff --git a/tests/auto/quick/qquicklistview/data/HighlightResize.qml b/tests/auto/quick/qquicklistview/data/HighlightResize.qml new file mode 100644 index 0000000000..2b07b39d20 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/HighlightResize.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 + +ListView { + id: view + + width: 400 + height: 400 + model: 5 + + highlight: Rectangle { + color: "skyblue" + } + + delegate: Item { + width: 100 + index * 20 + height: 100 + index * 10 + + Text { + anchors.centerIn: parent + text: model.index + } + } +} diff --git a/tests/auto/quick/qquicklistview/data/headerchangesviewport.qml b/tests/auto/quick/qquicklistview/data/headerchangesviewport.qml new file mode 100644 index 0000000000..b32f7a1236 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/headerchangesviewport.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +Rectangle { + width: 240 + height: 320 + color: "#ffffff" + ListView { + id: list + anchors.fill: parent + objectName: "list" + delegate: Text {} + header: Text { + objectName: "header" + text: "ninjas" + height: headerHeight + width: headerWidth + } + } +} diff --git a/tests/auto/quick/qquicklistview/data/listview-sections.qml b/tests/auto/quick/qquicklistview/data/listview-sections.qml index d5b8a4400d..e9fb83910a 100644 --- a/tests/auto/quick/qquicklistview/data/listview-sections.qml +++ b/tests/auto/quick/qquicklistview/data/listview-sections.qml @@ -1,6 +1,7 @@ import QtQuick 2.0 Rectangle { + property bool sectionsInvalidOnCompletion width: 240 height: 320 color: "#ffffff" @@ -9,6 +10,26 @@ Rectangle { id: myDelegate Item { id: wrapper + + function validateInitialSections() { + var invalid = false + if (index == 0) { + invalid |= wrapper.ListView.previousSection != "" + } + if (index == model.count - 1) { + invalid |= wrapper.ListView.nextSection != "" + } + if (index % 5 == 0 && index > 0) { + invalid |= wrapper.ListView.previousSection != Number(wrapper.ListView.section) - 1 + } else if ((index + 1) % 5 == 0 && index < model.count - 1) { + invalid |= wrapper.ListView.nextSection != Number(wrapper.ListView.section) + 1 + } else if (index > 0 && index < model.count - 1) { + invalid |= wrapper.ListView.previousSection != wrapper.ListView.section + invalid |= wrapper.ListView.nextSection != wrapper.ListView.section + } + sectionsInvalidOnCompletion |= invalid + } + objectName: "wrapper" height: ListView.previousSection != ListView.section ? 40 : 20; width: 240 @@ -49,6 +70,10 @@ Rectangle { visible: wrapper.ListView.previousSection != wrapper.ListView.section ? true : false Text { text: wrapper.ListView.section } } + ListView.onPreviousSectionChanged: validateInitialSections() + ListView.onNextSectionChanged: validateInitialSections() + ListView.onSectionChanged: validateInitialSections() + Component.onCompleted: validateInitialSections() } } ] diff --git a/tests/auto/quick/qquicklistview/data/typedModel.qml b/tests/auto/quick/qquicklistview/data/typedModel.qml new file mode 100644 index 0000000000..d2b3f7e42f --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/typedModel.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 + +ListView { + width: 100 + height: 100 + + delegate: Item { + width: 100 + height: 10 + } + model: listModel + + ListModel { + id: listModel + + ListElement { label: "a" } + ListElement { label: "b" } + ListElement { label: "c" } + ListElement { label: "d" } + ListElement { label: "e" } + ListElement { label: "f" } + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index f62151c2d8..d207a7eadc 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -150,6 +150,7 @@ private slots: void header(); void header_data(); void header_delayItemCreation(); + void headerChangesViewport(); void footer(); void footer_data(); void extents(); @@ -213,6 +214,10 @@ private slots: void outsideViewportChangeNotAffectingView(); void testProxyModelChangedAfterMove(); + void typedModel(); + + void highlightItemGeometryChanges(); + private: template <class T> void items(const QUrl &source); template <class T> void changed(const QUrl &source); @@ -1953,6 +1958,8 @@ void tst_QQuickListView::sections(const QUrl &source) QCOMPARE(next->text().toInt(), (i+1)/5); } + QVERIFY(!listview->property("sectionsInvalidOnCompletion").toBool()); + QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged())); // Remove section boundary @@ -3655,6 +3662,35 @@ void tst_QQuickListView::header_delayItemCreation() delete window; } +void tst_QQuickListView::headerChangesViewport() +{ + QQuickView *window = getView(); + window->rootContext()->setContextProperty("headerHeight", 20); + window->rootContext()->setContextProperty("headerWidth", 240); + window->setSource(testFileUrl("headerchangesviewport.qml")); + + QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + + QQuickItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QQuickText *header = 0; + QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header")); + QVERIFY(header == listview->headerItem()); + + QCOMPARE(header->height(), 20.); + QCOMPARE(listview->contentHeight(), 20.); + + // change height + window->rootContext()->setContextProperty("headerHeight", 50); + + // verify that list content height updates also + QCOMPARE(header->height(), 50.); + QCOMPARE(listview->contentHeight(), 50.); +} + void tst_QQuickListView::footer() { QFETCH(QQuickListView::Orientation, orientation); @@ -6960,6 +6996,43 @@ void tst_QQuickListView::testProxyModelChangedAfterMove() delete window; } +void tst_QQuickListView::typedModel() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("typedModel.qml")); + + QScopedPointer<QObject> object(component.create()); + + QQuickListView *listview = qobject_cast<QQuickListView *>(object.data()); + QVERIFY(listview); + + QCOMPARE(listview->count(), 6); + + QQmlListModel *listModel = 0; + + listview->setModel(QVariant::fromValue(listModel)); + QCOMPARE(listview->count(), 0); +} + +void tst_QQuickListView::highlightItemGeometryChanges() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("HighlightResize.qml")); + + QScopedPointer<QObject> object(component.create()); + + QQuickListView *listview = qobject_cast<QQuickListView *>(object.data()); + QVERIFY(listview); + + QCOMPARE(listview->count(), 5); + + for (int i = 0; i < listview->count(); ++i) { + listview->setCurrentIndex(i); + QTRY_COMPARE(listview->highlightItem()->width(), qreal(100 + i * 20)); + QTRY_COMPARE(listview->highlightItem()->height(), qreal(100 + i * 10)); + } +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" diff --git a/tests/auto/quick/qquickloader/data/SimpleTestComponent.qml b/tests/auto/quick/qquickloader/data/SimpleTestComponent.qml new file mode 100644 index 0000000000..0e69012662 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/SimpleTestComponent.qml @@ -0,0 +1,2 @@ +import QtQml 2.0 +QtObject {} diff --git a/tests/auto/quick/qquickloader/data/sourceComponentGarbageCollection.qml b/tests/auto/quick/qquickloader/data/sourceComponentGarbageCollection.qml new file mode 100644 index 0000000000..ab86883af5 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/sourceComponentGarbageCollection.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 + +Loader { + active: false + function setSourceComponent() { + sourceComponent = Qt.createComponent("SimpleTestComponent.qml"); + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index 50ded4d95a..1e23d689ff 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -128,6 +128,8 @@ private slots: void sizeBound(); void QTBUG_30183(); + void sourceComponentGarbageCollection(); + private: QQmlEngine engine; }; @@ -1144,6 +1146,26 @@ void tst_QQuickLoader::QTBUG_30183() delete loader; } +void tst_QQuickLoader::sourceComponentGarbageCollection() +{ + QQmlComponent component(&engine, testFileUrl("sourceComponentGarbageCollection.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + + QMetaObject::invokeMethod(obj.data(), "setSourceComponent"); + engine.collectGarbage(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + + QSignalSpy spy(obj.data(), SIGNAL(loaded())); + + obj->setProperty("active", true); + + if (spy.isEmpty()) + QVERIFY(spy.wait()); + + QCOMPARE(spy.count(), 1); +} + QTEST_MAIN(tst_QQuickLoader) #include "tst_qquickloader.moc" diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 72639556ec..31b323af5d 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -89,6 +89,7 @@ private slots: void dragThreshold(); void invalidDrag_data() { rejectedButton_data(); } void invalidDrag(); + void cancelDragging(); void setDragOnPressed(); void updateMouseAreaPosOnClick(); void updateMouseAreaPosOnResize(); @@ -440,6 +441,57 @@ void tst_QQuickMouseArea::invalidDrag() QCOMPARE(blackRect->y(), 50.0); } +void tst_QQuickMouseArea::cancelDragging() +{ + QQuickView window; + QByteArray errorMessage; + QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData()); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QVERIFY(window.rootObject() != 0); + + QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion"); + QQuickDrag *drag = mouseRegion->drag(); + QVERIFY(mouseRegion != 0); + QVERIFY(drag != 0); + + mouseRegion->setAcceptedButtons(Qt::LeftButton); + + // target + QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect"); + QVERIFY(blackRect != 0); + QVERIFY(blackRect == drag->target()); + + QVERIFY(!drag->active()); + + QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100)); + + QVERIFY(!drag->active()); + QCOMPARE(blackRect->x(), 50.0); + QCOMPARE(blackRect->y(), 50.0); + + QTest::mouseMove(&window, QPoint(111,111), 50); + QTest::mouseMove(&window, QPoint(116,116), 50); + QTest::mouseMove(&window, QPoint(122,122), 50); + + QTRY_VERIFY(drag->active()); + QTRY_COMPARE(blackRect->x(), 61.0); + QCOMPARE(blackRect->y(), 61.0); + + mouseRegion->QQuickItem::ungrabMouse(); + QTRY_VERIFY(!drag->active()); + QCOMPARE(blackRect->x(), 61.0); + QCOMPARE(blackRect->y(), 61.0); + + QTest::mouseMove(&window, QPoint(132,132), 50); + QTRY_VERIFY(!drag->active()); + QCOMPARE(blackRect->x(), 61.0); + QCOMPARE(blackRect->y(), 61.0); + + QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(122,122)); +} + void tst_QQuickMouseArea::setDragOnPressed() { QQuickView window; diff --git a/tests/auto/quick/qquicktextinput/data/signal_accepted.qml b/tests/auto/quick/qquicktextinput/data/signal_accepted.qml new file mode 100644 index 0000000000..94c113dd9f --- /dev/null +++ b/tests/auto/quick/qquicktextinput/data/signal_accepted.qml @@ -0,0 +1,14 @@ +import QtQuick 2.2 + +Item { + property QtObject input: input + + width: 800; height: 600; + + Column{ + TextInput { id: input; + property bool acceptable: acceptableInput + validator: RegExpValidator { regExp: /[a-zA-z]{2,4}/ } + } + } +} diff --git a/tests/auto/quick/qquicktextinput/data/signal_editingfinished.qml b/tests/auto/quick/qquicktextinput/data/signal_editingfinished.qml index 2ec5ce6676..dba186e765 100644 --- a/tests/auto/quick/qquicktextinput/data/signal_editingfinished.qml +++ b/tests/auto/quick/qquicktextinput/data/signal_editingfinished.qml @@ -1,13 +1,19 @@ import QtQuick 2.2 Item { - property variant input1: input1 - property variant input2: input2 + property QtObject input1: input1 + property QtObject input2: input2 width: 800; height: 600; Column{ - TextInput { id: input1; } - TextInput { id: input2; } + TextInput { id: input1; + property bool acceptable: acceptableInput + validator: RegExpValidator { regExp: /[a-zA-z]{2,4}/ } + } + TextInput { id: input2; + property bool acceptable: acceptableInput + validator: RegExpValidator { regExp: /[a-zA-z]{2,4}/ } + } } } diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index 80726720e4..697dba182c 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -49,6 +49,7 @@ #include <QtQuick/qquickview.h> #include <QtGui/qguiapplication.h> #include <QtGui/qstylehints.h> +#include <QtGui/qvalidator.h> #include <QInputMethod> #include <private/qquicktextinput_p.h> #include <private/qquicktextinput_p_p.h> @@ -146,6 +147,7 @@ private slots: void validators(); void inputMethods(); + void signal_accepted(); void signal_editingfinished(); void passwordCharacter(); @@ -226,6 +228,7 @@ private slots: void hasAcceptableInputMask(); void maskCharacter_data(); void maskCharacter(); + void fixup(); private: void simulateKey(QWindow *, int key); @@ -1271,10 +1274,9 @@ void tst_qquicktextinput::dragMouseSelection() QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y)); QTest::mouseMove(&window, QPoint(x2, y)); QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y)); - QTest::qWait(100); QString str1; - QVERIFY((str1 = textInputObject->selectedText()).length() > 3); - QVERIFY(str1.length() > 3); + QTRY_VERIFY((str1 = textInputObject->selectedText()).length() > 3); + QTRY_VERIFY(str1.length() > 3); // press and drag the current selection. x1 = 40; @@ -1282,11 +1284,10 @@ void tst_qquicktextinput::dragMouseSelection() QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y)); QTest::mouseMove(&window, QPoint(x2, y)); QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y)); - QTest::qWait(300); QString str2 = textInputObject->selectedText(); - QVERIFY(str2.length() > 3); + QTRY_VERIFY(str2.length() > 3); - QVERIFY(str1 != str2); + QTRY_VERIFY(str1 != str2); } void tst_qquicktextinput::mouseSelectionMode_data() @@ -1337,7 +1338,6 @@ void tst_qquicktextinput::mouseSelectionMode() QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y)); QTest::mouseMove(&window, QPoint(x2,y)); // doesn't work QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y)); - QTest::qWait(300); if (selectWords) { QTRY_COMPARE(textInputObject->selectedText(), text); } else { @@ -1873,8 +1873,7 @@ void tst_qquicktextinput::maxLength() QTRY_COMPARE(textinputObject->text().length(), qMin(i,10)); //simulateKey(&window, Qt::Key_A); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); } } @@ -1900,8 +1899,7 @@ void tst_qquicktextinput::masks() QCOMPARE(i>=4, textinputObject->hasAcceptableInput()); //simulateKey(&window, Qt::Key_A); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); } } @@ -1944,56 +1942,47 @@ void tst_qquicktextinput::validators() QCOMPARE(intInput->hasAcceptableInput(), false); QCOMPARE(intInput->property("acceptable").toBool(), false); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1")); QCOMPARE(intInput->hasAcceptableInput(), false); QCOMPARE(intInput->property("acceptable").toBool(), false); QCOMPARE(intSpy.count(), 0); QTest::keyPress(&window, Qt::Key_2); - QTest::keyRelease(&window, Qt::Key_2, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_2, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1")); QCOMPARE(intInput->hasAcceptableInput(), false); QCOMPARE(intInput->property("acceptable").toBool(), false); QCOMPARE(intSpy.count(), 0); QTest::keyPress(&window, Qt::Key_Period); - QTest::keyRelease(&window, Qt::Key_Period, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Period, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1")); QCOMPARE(intInput->hasAcceptableInput(), false); QTest::keyPress(&window, Qt::Key_Comma); - QTest::keyRelease(&window, Qt::Key_Comma, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Comma, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1,")); QCOMPARE(intInput->hasAcceptableInput(), false); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1")); QCOMPARE(intInput->hasAcceptableInput(), false); intValidator->setLocaleName(deLocale.name()); QTest::keyPress(&window, Qt::Key_Period); - QTest::keyRelease(&window, Qt::Key_Period, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Period, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1.")); QCOMPARE(intInput->hasAcceptableInput(), false); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(intInput->text(), QLatin1String("1")); QCOMPARE(intInput->hasAcceptableInput(), false); intValidator->resetLocaleName(); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QCOMPARE(intInput->text(), QLatin1String("11")); QCOMPARE(intInput->hasAcceptableInput(), true); QCOMPARE(intInput->property("acceptable").toBool(), true); QCOMPARE(intSpy.count(), 1); QTest::keyPress(&window, Qt::Key_0); - QTest::keyRelease(&window, Qt::Key_0, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_0, Qt::NoModifier); QCOMPARE(intInput->text(), QLatin1String("11")); QCOMPARE(intInput->hasAcceptableInput(), true); QCOMPARE(intInput->property("acceptable").toBool(), true); @@ -2019,81 +2008,68 @@ void tst_qquicktextinput::validators() QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("1")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 0); QTest::keyPress(&window, Qt::Key_2); - QTest::keyRelease(&window, Qt::Key_2, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_2, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12")); QCOMPARE(dblInput->hasAcceptableInput(), true); QCOMPARE(dblInput->property("acceptable").toBool(), true); QCOMPARE(dblSpy.count(), 1); QTest::keyPress(&window, Qt::Key_Comma); - QTest::keyRelease(&window, Qt::Key_Comma, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Comma, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12,")); QCOMPARE(dblInput->hasAcceptableInput(), true); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12,")); QCOMPARE(dblInput->hasAcceptableInput(), true); dblValidator->setLocaleName(deLocale.name()); QCOMPARE(dblInput->hasAcceptableInput(), true); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12,1")); QCOMPARE(dblInput->hasAcceptableInput(), true); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12,11")); QCOMPARE(dblInput->hasAcceptableInput(), true); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12,1")); QCOMPARE(dblInput->hasAcceptableInput(), true); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12,")); QCOMPARE(dblInput->hasAcceptableInput(), true); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12")); QCOMPARE(dblInput->hasAcceptableInput(), true); dblValidator->resetLocaleName(); QTest::keyPress(&window, Qt::Key_Period); - QTest::keyRelease(&window, Qt::Key_Period, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Period, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.")); QCOMPARE(dblInput->hasAcceptableInput(), true); QCOMPARE(dblInput->property("acceptable").toBool(), true); QCOMPARE(dblSpy.count(), 1); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.1")); QCOMPARE(dblInput->hasAcceptableInput(), true); QCOMPARE(dblInput->property("acceptable").toBool(), true); QCOMPARE(dblSpy.count(), 1); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.11")); QCOMPARE(dblInput->hasAcceptableInput(), true); QCOMPARE(dblInput->property("acceptable").toBool(), true); QCOMPARE(dblSpy.count(), 1); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.11")); QCOMPARE(dblInput->hasAcceptableInput(), true); QCOMPARE(dblInput->property("acceptable").toBool(), true); @@ -2106,50 +2082,43 @@ void tst_qquicktextinput::validators() QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 2); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.1")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 2); // Once unacceptable input is in anything goes until it reaches an acceptable state again. QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.11")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblSpy.count(), 2); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.1")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 2); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12.")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 2); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("12")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 2); QTest::keyPress(&window, Qt::Key_Backspace); - QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier); QTRY_COMPARE(dblInput->text(), QLatin1String("1")); QCOMPARE(dblInput->hasAcceptableInput(), false); QCOMPARE(dblInput->property("acceptable").toBool(), false); QCOMPARE(dblSpy.count(), 2); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QCOMPARE(dblInput->text(), QLatin1String("11")); QCOMPARE(dblInput->property("acceptable").toBool(), true); QCOMPARE(dblInput->hasAcceptableInput(), true); @@ -2173,43 +2142,37 @@ void tst_qquicktextinput::validators() QCOMPARE(strInput->hasAcceptableInput(), false); QCOMPARE(strInput->property("acceptable").toBool(), false); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(strInput->text(), QLatin1String("")); QCOMPARE(strInput->hasAcceptableInput(), false); QCOMPARE(strInput->property("acceptable").toBool(), false); QCOMPARE(strSpy.count(), 0); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(strInput->text(), QLatin1String("a")); QCOMPARE(strInput->hasAcceptableInput(), false); QCOMPARE(strInput->property("acceptable").toBool(), false); QCOMPARE(strSpy.count(), 0); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(strInput->text(), QLatin1String("aa")); QCOMPARE(strInput->hasAcceptableInput(), true); QCOMPARE(strInput->property("acceptable").toBool(), true); QCOMPARE(strSpy.count(), 1); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(strInput->text(), QLatin1String("aaa")); QCOMPARE(strInput->hasAcceptableInput(), true); QCOMPARE(strInput->property("acceptable").toBool(), true); QCOMPARE(strSpy.count(), 1); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(strInput->text(), QLatin1String("aaaa")); QCOMPARE(strInput->hasAcceptableInput(), true); QCOMPARE(strInput->property("acceptable").toBool(), true); QCOMPARE(strSpy.count(), 1); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(strInput->text(), QLatin1String("aaaa")); QCOMPARE(strInput->hasAcceptableInput(), true); QCOMPARE(strInput->property("acceptable").toBool(), true); @@ -2223,15 +2186,13 @@ void tst_qquicktextinput::validators() QCOMPARE(unvalidatedInput->hasAcceptableInput(), true); QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true); QTest::keyPress(&window, Qt::Key_1); - QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier); QTRY_COMPARE(unvalidatedInput->text(), QLatin1String("1")); QCOMPARE(unvalidatedInput->hasAcceptableInput(), true); QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true); QCOMPARE(unvalidatedSpy.count(), 0); QTest::keyPress(&window, Qt::Key_A); - QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier ,10); - QTest::qWait(50); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(unvalidatedInput->text(), QLatin1String("1a")); QCOMPARE(unvalidatedInput->hasAcceptableInput(), true); QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true); @@ -2305,6 +2266,48 @@ void tst_qquicktextinput::inputMethods() QCOMPARE(enabledQueryEvent.value(Qt::ImEnabled).toBool(), false); } +void tst_qquicktextinput::signal_accepted() +{ + QQuickView window(testFileUrl("signal_accepted.qml")); + window.show(); + window.requestActivate(); + QTest::qWaitForWindowActive(&window); + + QVERIFY(window.rootObject() != 0); + + QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("input"))); + QVERIFY(input); + QSignalSpy acceptedSpy(input, SIGNAL(accepted())); + QSignalSpy inputSpy(input, SIGNAL(acceptableInputChanged())); + + input->setFocus(true); + QTRY_VERIFY(input->hasActiveFocus()); + QCOMPARE(input->hasAcceptableInput(), false); + QCOMPARE(input->property("acceptable").toBool(), false); + + QTest::keyPress(&window, Qt::Key_A); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); + QTRY_COMPARE(input->text(), QLatin1String("a")); + QCOMPARE(input->hasAcceptableInput(), false); + QCOMPARE(input->property("acceptable").toBool(), false); + QTRY_COMPARE(inputSpy.count(), 0); + + QTest::keyPress(&window, Qt::Key_Enter); + QTest::keyRelease(&window, Qt::Key_Enter, Qt::NoModifier); + QTRY_COMPARE(acceptedSpy.count(), 0); + + QTest::keyPress(&window, Qt::Key_A); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); + QTRY_COMPARE(input->text(), QLatin1String("aa")); + QCOMPARE(input->hasAcceptableInput(), true); + QCOMPARE(input->property("acceptable").toBool(), true); + QTRY_COMPARE(inputSpy.count(), 1); + + QTest::keyPress(&window, Qt::Key_Enter); + QTest::keyRelease(&window, Qt::Key_Enter, Qt::NoModifier); + QTRY_COMPARE(acceptedSpy.count(), 1); +} + void tst_qquicktextinput::signal_editingfinished() { QQuickView window(testFileUrl("signal_editingfinished.qml")); @@ -2318,7 +2321,8 @@ void tst_qquicktextinput::signal_editingfinished() QVERIFY(input1); QQuickTextInput *input2 = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("input2"))); QVERIFY(input2); - QSignalSpy input1Spy(input1, SIGNAL(editingFinished())); + QSignalSpy editingFinished1Spy(input1, SIGNAL(editingFinished())); + QSignalSpy input1Spy(input1, SIGNAL(acceptableInputChanged())); input1->setFocus(true); QTRY_VERIFY(input1->hasActiveFocus()); @@ -2327,12 +2331,28 @@ void tst_qquicktextinput::signal_editingfinished() QTest::keyPress(&window, Qt::Key_A); QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(input1->text(), QLatin1String("a")); + QCOMPARE(input1->hasAcceptableInput(), false); + QCOMPARE(input1->property("acceptable").toBool(), false); + QTRY_COMPARE(input1Spy.count(), 0); + + QTest::keyPress(&window, Qt::Key_Enter); + QTest::keyRelease(&window, Qt::Key_Enter, Qt::NoModifier); + QTRY_COMPARE(editingFinished1Spy.count(), 0); + + QTest::keyPress(&window, Qt::Key_A); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); + QTRY_COMPARE(input1->text(), QLatin1String("aa")); + QCOMPARE(input1->hasAcceptableInput(), true); + QCOMPARE(input1->property("acceptable").toBool(), true); + QTRY_COMPARE(input1Spy.count(), 1); QTest::keyPress(&window, Qt::Key_Enter); QTest::keyRelease(&window, Qt::Key_Enter, Qt::NoModifier); + QTRY_COMPARE(editingFinished1Spy.count(), 1); QTRY_COMPARE(input1Spy.count(), 1); - QSignalSpy input2Spy(input2, SIGNAL(editingFinished())); + QSignalSpy editingFinished2Spy(input2, SIGNAL(editingFinished())); + QSignalSpy input2Spy(input2, SIGNAL(acceptableInputChanged())); input2->setFocus(true); QTRY_VERIFY(!input1->hasActiveFocus()); @@ -2341,11 +2361,21 @@ void tst_qquicktextinput::signal_editingfinished() QTest::keyPress(&window, Qt::Key_A); QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); QTRY_COMPARE(input2->text(), QLatin1String("a")); + QCOMPARE(input2->hasAcceptableInput(), false); + QCOMPARE(input2->property("acceptable").toBool(), false); + QTRY_COMPARE(input2Spy.count(), 0); + + QTest::keyPress(&window, Qt::Key_A); + QTest::keyRelease(&window, Qt::Key_A, Qt::NoModifier); + QTRY_COMPARE(input2->text(), QLatin1String("aa")); + QCOMPARE(input2->hasAcceptableInput(), true); + QCOMPARE(input2->property("acceptable").toBool(), true); + QTRY_COMPARE(input2Spy.count(), 1); input1->setFocus(true); QTRY_VERIFY(input1->hasActiveFocus()); QTRY_VERIFY(!input2->hasActiveFocus()); - QTRY_COMPARE(input2Spy.count(), 1); + QTRY_COMPARE(editingFinished2Spy.count(), 1); } /* @@ -6296,6 +6326,38 @@ void tst_qquicktextinput::maskCharacter() } } +class TestValidator : public QValidator +{ +public: + TestValidator(QObject *parent = 0) : QValidator(parent) { } + + State validate(QString &input, int &) const { return input == QStringLiteral("ok") ? Acceptable : Intermediate; } + void fixup(QString &input) const { input = QStringLiteral("ok"); } +}; + +void tst_qquicktextinput::fixup() +{ + QQuickWindow window; + window.show(); + window.requestActivate(); + QTest::qWaitForWindowActive(&window); + + QQuickTextInput *input = new QQuickTextInput(window.contentItem()); + input->setValidator(new TestValidator(input)); + + // fixup() on accept + input->setFocus(true); + QVERIFY(input->hasActiveFocus()); + QTest::keyClick(&window, Qt::Key_Enter); + QCOMPARE(input->text(), QStringLiteral("ok")); + + // fixup() on defocus + input->setText(QString()); + input->setFocus(false); + QVERIFY(!input->hasActiveFocus()); + QCOMPARE(input->text(), QStringLiteral("ok")); +} + QTEST_MAIN(tst_qquicktextinput) #include "tst_qquicktextinput.moc" diff --git a/tests/auto/quick/qquickwindow/data/focus.qml b/tests/auto/quick/qquickwindow/data/focus.qml index 899b999cdc..fa8ae9dc69 100644 --- a/tests/auto/quick/qquickwindow/data/focus.qml +++ b/tests/auto/quick/qquickwindow/data/focus.qml @@ -12,4 +12,8 @@ Window.Window { Item { objectName: "item2" } + + FocusScope { + Item { objectName: "item3" } + } } diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index b09f80a634..107d1d71f7 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -1145,20 +1145,35 @@ void tst_qquickwindow::focusObject() QQuickWindow *window = qobject_cast<QQuickWindow*>(created); QVERIFY(window); + QSignalSpy focusObjectSpy(window, SIGNAL(focusObjectChanged(QObject*))); + window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); QVERIFY(QTest::qWaitForWindowActive(window)); + QCOMPARE(window->contentItem(), window->focusObject()); + QCOMPARE(focusObjectSpy.count(), 1); + QQuickItem *item1 = window->findChild<QQuickItem*>("item1"); QVERIFY(item1); item1->setFocus(true); QCOMPARE(item1, window->focusObject()); + QCOMPARE(focusObjectSpy.count(), 2); QQuickItem *item2 = window->findChild<QQuickItem*>("item2"); QVERIFY(item2); item2->setFocus(true); QCOMPARE(item2, window->focusObject()); + QCOMPARE(focusObjectSpy.count(), 3); + + // set focus for item in non-focused focus scope and + // ensure focusObject does not change and signal is not emitted + QQuickItem *item3 = window->findChild<QQuickItem*>("item3"); + QVERIFY(item3); + item3->setFocus(true); + QCOMPARE(item2, window->focusObject()); + QCOMPARE(focusObjectSpy.count(), 3); } void tst_qquickwindow::ignoreUnhandledMouseEvents() diff --git a/tests/auto/quick/scenegraph/data/simple.qml b/tests/auto/quick/scenegraph/data/simple.qml new file mode 100644 index 0000000000..b2924f135e --- /dev/null +++ b/tests/auto/quick/scenegraph/data/simple.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 + +Rectangle { + width: 200 + height: 200 + color: "steelblue" + Rectangle { + width: 150 + height: 150 + anchors.centerIn: parent + color: "palegreen" + rotation: 45 + Text { + rotation: -45 + text: "Simple QML.." + anchors.centerIn: parent + } + } +} diff --git a/tests/auto/quick/scenegraph/scenegraph.pro b/tests/auto/quick/scenegraph/scenegraph.pro index 105221b7f4..1aa73ca60a 100644 --- a/tests/auto/quick/scenegraph/scenegraph.pro +++ b/tests/auto/quick/scenegraph/scenegraph.pro @@ -11,4 +11,5 @@ QT += core-private gui-private qml-private quick-private testlib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 OTHER_FILES += \ - data/render_OutOfFloatRange.qml + data/render_OutOfFloatRange.qml \ + data/simple.qml diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp index 3b79f01f12..780d5a97db 100644 --- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp +++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp @@ -58,6 +58,8 @@ private slots: void render_data(); void render(); + + void hideWithOtherContext(); }; template <typename T> class ScopedList : public QList<T> { @@ -401,6 +403,40 @@ void tst_SceneGraph::render() } } +// Testcase for QTBUG-34898. We make another context current on another surface +// in the GUI thread and hide the QQuickWindow while the other context is +// current on the other window. +void tst_SceneGraph::hideWithOtherContext() +{ + QWindow window; + window.setSurfaceType(QWindow::OpenGLSurface); + window.resize(100, 100); + window.create(); + QOpenGLContext context; + context.create(); + bool renderingOnMainThread = false; + + { + QQuickView view; + view.setSource(QUrl::fromLocalFile("data/simple.qml")); + view.setResizeMode(QQuickView::SizeViewToRootObject); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + renderingOnMainThread = view.openglContext()->thread() == QGuiApplication::instance()->thread(); + + // Make the local context current on the local window... + context.makeCurrent(&window); + } + + // The local context should no longer be the current one. It is not + // rebound because all well behaving Qt/OpenGL applications are + // required to makeCurrent their context again before making any + // GL calls to a new frame (see QOpenGLContext docs). + QVERIFY(!renderingOnMainThread || QOpenGLContext::currentContext() != &context); +} + + #include "tst_scenegraph.moc" QTEST_MAIN(tst_SceneGraph) diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp index fd681710de..20df0c12f5 100644 --- a/tests/auto/shared/testhttpserver.cpp +++ b/tests/auto/shared/testhttpserver.cpp @@ -88,7 +88,7 @@ The following request urls will then result in the appropriate action: \endtable */ TestHTTPServer::TestHTTPServer(quint16 port) -: m_hasFailed(false) +: m_state(AwaitingHeader) { QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection())); @@ -122,7 +122,8 @@ void TestHTTPServer::addRedirect(const QString &filename, const QString &redirec bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &body) { - m_hasFailed = false; + m_state = AwaitingHeader; + m_data.clear(); QFile expectFile(expect.toLocalFile()); if (!expectFile.open(QIODevice::ReadOnly)) return false; @@ -175,7 +176,7 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod bool TestHTTPServer::hasFailed() const { - return m_hasFailed; + return m_state == Failed; } void TestHTTPServer::newConnection() @@ -216,33 +217,41 @@ void TestHTTPServer::readyRead() return; } - if (m_hasFailed || (waitData.body.isEmpty() && waitData.headers.count() == 0)) { + if (m_state == Failed || (waitData.body.isEmpty() && waitData.headers.count() == 0)) { qWarning() << "TestHTTPServer: Unexpected data" << socket->readAll(); return; } - QByteArray line; - while (!(line = socket->readLine()).isEmpty()) { - line.replace('\r', ""); - if (line.at(0) == '\n') { - QByteArray data = socket->readAll(); - if (waitData.body != data) { - qWarning() << "TestHTTPServer: Unexpected data" << data << "\nExpected: " << waitData.body; - m_hasFailed = true; - socket->disconnectFromHost(); - return; + if (m_state == AwaitingHeader) { + QByteArray line; + while (!(line = socket->readLine()).isEmpty()) { + line.replace('\r', ""); + if (line.at(0) == '\n') { + m_state = AwaitingData; + m_data += socket->readAll(); + break; + } else { + if (!waitData.headers.contains(line)) { + qWarning() << "TestHTTPServer: Unexpected header:" << line << "\nExpected headers: " << waitData.headers; + m_state = Failed; + socket->disconnectFromHost(); + return; + } } } - else if (!waitData.headers.contains(line)) { - qWarning() << "TestHTTPServer: Unexpected header:" << line << "\nExpected headers: " << waitData.headers; - m_hasFailed = true; - socket->disconnectFromHost(); - return; - } + } else { + m_data += socket->readAll(); } - socket->write(replyData); - socket->disconnectFromHost(); + if (!m_data.isEmpty() || waitData.body.isEmpty()) { + if (waitData.body != m_data) { + qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << waitData.body; + m_state = Failed; + } else { + socket->write(replyData); + } + socket->disconnectFromHost(); + } } bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) diff --git a/tests/auto/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h index ce0501f170..ae7d137143 100644 --- a/tests/auto/shared/testhttpserver.h +++ b/tests/auto/shared/testhttpserver.h @@ -74,6 +74,12 @@ private slots: void sendOne(); private: + enum State { + AwaitingHeader, + AwaitingData, + Failed + }; + void serveGET(QTcpSocket *, const QByteArray &); bool reply(QTcpSocket *, const QByteArray &); @@ -87,7 +93,8 @@ private: } waitData; QByteArray replyData; QByteArray bodyData; - bool m_hasFailed; + QByteArray m_data; + State m_state; QHash<QString,QString> aliases; QHash<QString,QString> redirects; |