From 52ac0ea8cbdc9a2b8e895ceee09994fba229ee12 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 8 Mar 2019 10:51:57 +0100 Subject: QUICK_TEST_MAIN_WITH_SETUP: fix qmlEngineAvailable() being called too late When I added the macro, I wasn't aware that TestCaseCollector was a thing. TestCaseCollector loads each QML file without running the tests (i.e. creates a QQmlComponent from the file without creating an object from that component). Since it still executes imports, the test can fail if types are registered or import paths added in qmlEngineAvailable(), since it's called too late. So, call it earlier. This should have no adverse effect on user code, as nothing of importance to the user will be skipped, and the documentation already details what can be expected by the time qmlEngineAvailable() is called. Change-Id: Ibd3a4b728bc87b90f89cc310fddf668c5879ad83 Fixes: QTBUG-74160 Reviewed-by: Ulf Hermann --- src/qmltest/quicktest.cpp | 15 +++++++-------- .../quicktest/quicktestmainwithsetup/data/tst_setup.qml | 6 ++++++ .../imports/ImportPathQmlModule/ImportPathQmlType.qml | 3 +++ .../imports/ImportPathQmlModule/qmldir | 2 ++ .../quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp | 14 ++++++++++++++ 5 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml create mode 100644 tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 1a5cad5d5a..5288bb34f1 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -503,6 +503,13 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch qmlFileSelector->setExtraSelectors(fileSelectors); } + // Do this down here so that import paths, plugin paths, file selectors, etc. are available + // in case the user needs access to them. Do it _before_ the TestCaseCollector parses the + // QML files though, because it attempts to import modules, which might not be available + // if qmlRegisterType()/QQmlEngine::addImportPath() are called in qmlEngineAvailable(). + if (setup) + QMetaObject::invokeMethod(setup, "qmlEngineAvailable", Q_ARG(QQmlEngine*, &engine)); + TestCaseCollector testCaseCollector(fi, &engine); if (!testCaseCollector.errors().isEmpty()) { for (const QQmlError &error : testCaseCollector.errors()) @@ -534,14 +541,6 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch view.rootContext()->setContextProperty (QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead - // Do this down here so that import paths, plugin paths, - // file selectors, etc. are available in case the user needs access to them. - if (setup) { - // Don't check the return value; it's OK if it doesn't exist. - // If we add more callbacks in the future, it makes sense if the user only implements one of them. - QMetaObject::invokeMethod(setup, "qmlEngineAvailable", Q_ARG(QQmlEngine*, view.engine())); - } - view.setObjectName(fi.baseName()); view.setTitle(view.objectName()); QTestRootObject::instance()->init(); diff --git a/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml b/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml index 0f5466998a..ea6b3e014b 100644 --- a/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml +++ b/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml @@ -29,9 +29,15 @@ import QtQuick 2.0 import QtTest 1.2 +import QmlRegisterTypeCppModule 1.0 +import ImportPathQmlModule 1.0 + TestCase { name: "setup" + QmlRegisterTypeCppType {} + ImportPathQmlType {} + function initTestCase() { verify(qmlEngineAvailableCalled) diff --git a/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml new file mode 100644 index 0000000000..617bdaaf67 --- /dev/null +++ b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml @@ -0,0 +1,3 @@ +import QtQuick 2.0 + +Item {} diff --git a/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir new file mode 100644 index 0000000000..dea7c9a8a4 --- /dev/null +++ b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir @@ -0,0 +1,2 @@ +module ImportPathQmlModule +ImportPathQmlType 1.0 ImportPathQmlType.qml diff --git a/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp b/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp index b0545d1a95..b5deeceac4 100644 --- a/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp +++ b/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp @@ -35,6 +35,14 @@ #include "../../shared/util.h" +class QmlRegisterTypeCppType : public QObject +{ + Q_OBJECT + +public: + QmlRegisterTypeCppType() {} +}; + class CustomTestSetup : public QObject { Q_OBJECT @@ -45,6 +53,12 @@ public: public slots: void qmlEngineAvailable(QQmlEngine *qmlEngine) { + // Test that modules are successfully imported by the TestCaseCollector that + // parses the QML files (but doesn't run them). For that to happen, qmlEngineAvailable() + // must be called before TestCaseCollector does its thing. + qmlRegisterType("QmlRegisterTypeCppModule", 1, 0, "QmlRegisterTypeCppType"); + qmlEngine->addImportPath(QString::fromUtf8(QT_QMLTEST_DATADIR) + "/../imports"); + qmlEngine->rootContext()->setContextProperty("qmlEngineAvailableCalled", true); } }; -- cgit v1.2.3