aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-01-23 10:03:00 +0100
committerUlf Hermann <ulf.hermann@qt.io>2023-01-27 10:42:06 +0100
commitddba87612d2be25863135669e81bc3391dc40e82 (patch)
tree839f35beafff47adeb1df12d2958cf8f36e9704a /tests/auto
parent08c086b9977d9275c53b58d6ffc766740e248c2c (diff)
QML: Turn singleton/type mismatch into a run time type error
There are many ways to "hide" the qmldir from the engine at run time, which turns singletons into regular types. While all of this is invalid, we should not assert on it, but rather produce a legible warning. Furthermore, sharpen the importing of extra modules from qrc as implicit imports. We should really only import modules the file in question can ever be part of. Otherwise we needlessly produce the above situation and hide legitimate warning messages. Amends commit 7517c1b3ae9aa92f36b19d74a4b2de5e8531309b. Now we need to teach our tools about the default import paths in the resorurce file system. They cannot guess any type they may find in any resource file anymore. Pick-to: 6.5 Task-number: QTBUG-106929 Change-Id: Ic8c02396d10830a7f461e8a81649bb8c9a1add1f Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp17
-rw-r--r--tests/auto/qml/qmllint/data/implicitImportResource.qrc1
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp31
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml1
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml1
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/uncreatable.qml1
-rw-r--r--tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp24
10 files changed, 74 insertions, 18 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 34865cb43c..0737d77005 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -105,6 +105,8 @@ set(qml_files
functionReturningVoid.qml
functionTakingVar.qml
globals.qml
+ hidden/Main.qml
+ hidden/Style.qml
idAccess.qml
immediateQuit.qml
imports/QmlBench/Globals.qml
@@ -209,6 +211,9 @@ set_source_files_properties("shared/Slider.qml"
PROPERTIES QT_RESOURCE_ALIAS "Slider.qml"
)
+set_source_files_properties("hidden/Style.qml"
+ PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
+
qt_add_library(codegen_test_module STATIC)
qt_autogen_tools_initial_setup(codegen_test_module)
diff --git a/tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml b/tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml
new file mode 100644
index 0000000000..dd97728433
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+QtObject {
+ property color c: Style.windowColor
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml b/tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml
new file mode 100644
index 0000000000..8bff4ef96b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQuick
+
+QtObject {
+ readonly property color windowColor: "#4CAF50"
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 8b2b4bbbf4..dd30931868 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -163,6 +163,7 @@ private slots:
void equalityQObjects();
void dateConversions();
void valueTypeBehavior();
+ void invisibleSingleton();
};
void tst_QmlCppCodegen::initTestCase()
@@ -3182,6 +3183,22 @@ void tst_QmlCppCodegen::valueTypeBehavior()
QCOMPARE(o2->property("f").toDouble(), 5.0);
}
+void tst_QmlCppCodegen::invisibleSingleton()
+{
+ QQmlEngine engine;
+ const QUrl copy(u"qrc:/qt/qml/TestTypes/hidden/Main.qml"_s);
+ QQmlComponent c(&engine, copy);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/hidden/Main.qml:4:5: "
+ "Unable to assign [undefined] to QColor");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("c"), QVariant(QMetaType::fromName("QColor")));
+}
+
QTEST_MAIN(tst_QmlCppCodegen)
#include "tst_qmlcppcodegen.moc"
diff --git a/tests/auto/qml/qmllint/data/implicitImportResource.qrc b/tests/auto/qml/qmllint/data/implicitImportResource.qrc
index e01bf3bb3e..026c8c4d4f 100644
--- a/tests/auto/qml/qmllint/data/implicitImportResource.qrc
+++ b/tests/auto/qml/qmllint/data/implicitImportResource.qrc
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
+ <file>additionalImplicitImport.qml</file>
<file alias="qmldir">Things/qmldir</file>
</qresource>
</RCC>
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index ce5e24ed5e..80c3d17d78 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -397,13 +397,29 @@ void TestQmllint::autoqmltypes()
void TestQmllint::resources()
{
- callQmllint(testFile("resource.qml"), true, nullptr, {}, {}, { testFile("resource.qrc") });
- callQmllint(testFile("badResource.qml"), false, nullptr, {}, {}, { testFile("resource.qrc") });
+ {
+ // We need to clear the import cache before we add a qrc file with different
+ // contents for the same paths.
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+
+ callQmllint(testFile("resource.qml"), true, nullptr, {}, {}, { testFile("resource.qrc") });
+ callQmllint(testFile("badResource.qml"), false, nullptr, {}, {}, { testFile("resource.qrc") });
+ }
+
+
callQmllint(testFile("resource.qml"), false);
callQmllint(testFile("badResource.qml"), true);
- callQmllint(testFile("T/b.qml"), true, nullptr, {}, {}, { testFile("T/a.qrc") });
- callQmllint(testFile("relPathQrc/Foo/Thing.qml"), true, nullptr, {}, {},
+
+ {
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+ callQmllint(testFile("T/b.qml"), true, nullptr, {}, {}, { testFile("T/a.qrc") });
+ }
+
+ {
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+ callQmllint(testFile("relPathQrc/Foo/Thing.qml"), true, nullptr, {}, {},
{ testFile("relPathQrc/resources.qrc") });
+ }
}
void TestQmllint::dirtyQmlCode_data()
@@ -1367,13 +1383,13 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
if (type == LintFile) {
lintResult = m_linter.lintFile(
- lintedFile, nullptr, true, warnings ? &jsonOutput : nullptr,
+ lintedFile, nullptr, true, &jsonOutput,
defaultImports == UseDefaultImports ? m_defaultImportPaths + importPaths
: importPaths,
qmldirFiles, resources,
categories != nullptr ? *categories : QQmlJSLogger::defaultCategories());
} else {
- lintResult = m_linter.lintModule(fileToLint, true, warnings ? &jsonOutput : nullptr);
+ lintResult = m_linter.lintModule(fileToLint, true, &jsonOutput);
}
bool success = lintResult == QQmlJSLinter::LintSuccess;
@@ -1602,8 +1618,11 @@ void TestQmllint::settingsFile()
void TestQmllint::additionalImplicitImport()
{
+ // We're polluting the resource file system here, so let's clean up afterwards.
+ const auto guard = qScopeGuard([this]() {m_linter.clearCache(); });
runTest("additionalImplicitImport.qml", Result::clean(), {}, {},
{ testFile("implicitImportResource.qrc") });
+
}
void TestQmllint::attachedPropertyReuse()
diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml b/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml
index a2a100ab3b..6570134ff9 100644
--- a/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml
+++ b/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml
@@ -1,3 +1,4 @@
+import QmltcQProcessTests
TypeWithSignals
{
diff --git a/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml b/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml
index d48a4ee186..210096b75f 100644
--- a/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml
+++ b/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml
@@ -1,4 +1,5 @@
pragma Singleton
+import QmltcQProcessTests
UncreatableType {
diff --git a/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml b/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml
index aad6ef3421..1a0e436665 100644
--- a/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml
+++ b/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml
@@ -1,4 +1,5 @@
import QtQuick
+import QmltcQProcessTests
Item {
// Illegal cases:
diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
index 1cea44206f..7f12f29342 100644
--- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
+++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
@@ -193,20 +193,20 @@ void tst_qmltc_qprocess::singleton()
{
{
const auto errors = runQmltc(u"singletonUncreatable.qml"_s, false);
- QVERIFY(errors.contains("singletonUncreatable.qml:3:1: Type UncreatableType is not "
+ QVERIFY(errors.contains("singletonUncreatable.qml:4:1: Type UncreatableType is not "
"creatable. [uncreatable-type]"));
}
{
const auto errors = runQmltc(u"uncreatable.qml"_s, false);
QVERIFY(errors.contains(
- "uncreatable.qml:5:5: Type UncreatableType is not creatable. [uncreatable-type]"));
- QVERIFY(errors.contains("uncreatable.qml:6:5: Singleton Type SingletonThing is not "
+ "uncreatable.qml:6:5: Type UncreatableType is not creatable. [uncreatable-type]"));
+ QVERIFY(errors.contains("uncreatable.qml:7:5: Singleton Type SingletonThing is not "
"creatable. [uncreatable-type]"));
- QVERIFY(errors.contains("uncreatable.qml:7:5: Singleton Type SingletonType is not "
+ QVERIFY(errors.contains("uncreatable.qml:8:5: Singleton Type SingletonType is not "
"creatable. [uncreatable-type]"));
- QVERIFY(errors.contains("uncreatable.qml:9:18: Singleton Type SingletonThing is not "
+ QVERIFY(errors.contains("uncreatable.qml:10:18: Singleton Type SingletonThing is not "
"creatable. [uncreatable-type]"));
- QVERIFY(errors.contains("uncreatable.qml:14:18: Singleton Type SingletonType is not "
+ QVERIFY(errors.contains("uncreatable.qml:15:18: Singleton Type SingletonType is not "
"creatable. [uncreatable-type]"));
QVERIFY(!errors.contains("NotSingletonType"));
}
@@ -247,17 +247,17 @@ void tst_qmltc_qprocess::invalidSignalHandlers()
{
const auto errors = runQmltc(u"invalidSignalHandlers.qml"_s, false);
QVERIFY(errors.contains(
- u"invalidSignalHandlers.qml:4:5: Type QFont of parameter in signal called signalWithConstPointerToGadget should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadget. [signal-handler-parameters]"_s));
+ u"invalidSignalHandlers.qml:5:5: Type QFont of parameter in signal called signalWithConstPointerToGadget should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadget. [signal-handler-parameters]"_s));
QVERIFY(errors.contains(
- u"invalidSignalHandlers.qml:5:5: Type QFont of parameter in signal called signalWithConstPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadgetConst. [signal-handler-parameters]"_s));
+ u"invalidSignalHandlers.qml:6:5: Type QFont of parameter in signal called signalWithConstPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadgetConst. [signal-handler-parameters]"_s));
QVERIFY(errors.contains(
- u"invalidSignalHandlers.qml:6:5: Type QFont of parameter in signal called signalWithPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithPointerToGadgetConst. [signal-handler-parameters]"_s));
+ u"invalidSignalHandlers.qml:7:5: Type QFont of parameter in signal called signalWithPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithPointerToGadgetConst. [signal-handler-parameters]"_s));
QVERIFY(errors.contains(
- u"invalidSignalHandlers.qml:7:5: Type QFont of parameter in signal called signalWithPointerToGadget should be passed by value or const reference to be able to compile onSignalWithPointerToGadget. [signal-handler-parameters]"_s));
+ u"invalidSignalHandlers.qml:8:5: Type QFont of parameter in signal called signalWithPointerToGadget should be passed by value or const reference to be able to compile onSignalWithPointerToGadget. [signal-handler-parameters]"_s));
QVERIFY(errors.contains(
- u"invalidSignalHandlers.qml:8:5: Type int of parameter in signal called signalWithPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithPrimitivePointer. [signal-handler-parameters]"_s));
+ u"invalidSignalHandlers.qml:9:5: Type int of parameter in signal called signalWithPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithPrimitivePointer. [signal-handler-parameters]"_s));
QVERIFY(errors.contains(
- u"invalidSignalHandlers.qml:9:5: Type int of parameter in signal called signalWithConstPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithConstPrimitivePointer. [signal-handler-parameters]"_s));
+ u"invalidSignalHandlers.qml:10:5: Type int of parameter in signal called signalWithConstPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithConstPrimitivePointer. [signal-handler-parameters]"_s));
}
}