QmlCompiler: Stabilize test

Loading the implicit import might add extra types that use up indices.
So, make sure the implicit import has already been loaded at that point.

Use a file that only has one type reference so that the ordering of type
references cannot mess up the selection of indices for types.

Change-Id: Ia33979e660e114ef608e1f5e22252c822c7f3d61
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Ulf Hermann 2023-08-22 13:30:37 +02:00
parent 4ae033fae3
commit 2eac7350c0
3 changed files with 58 additions and 26 deletions

View File

@ -39,6 +39,7 @@ set(qml_files
Cycle2.qml
Cycle3.qml
Dummy.qml
Dummy2.qml
Enums.qml
Foozle.qml
Loopy.qml

View File

@ -0,0 +1,18 @@
// Copyright (C) 2020 The Qt Company Ltd.
import QtQml
QtObject {
property int value
property Dummy2 child
property int dummyEnum
signal triggered()
signal signalWithArg(int one, bool two)
property real onValue
property real offValue
function someFunction(a: int, b: bool, c: Dummy2, d: real, e: int) : int { return 42 }
property string strProp
function concat(a: string, b: string) : string { return a + b }
}

View File

@ -221,26 +221,6 @@ extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[];
}
}
// QML-generated types have no C++ names, but we want to call a method that
// expects a pointer to a QML-generated type as argument.
//
// We force the QML engine to assign a specific name to our type and declare
// an incomplete dummy class of the same name here. The dummy class does not
// have a proper metatype by itself. Therefore, when we want to pass a (null)
// pointer of it to invokeMethod(), usually invokeMethod() would complain that
// the metatype of the argument we pass does not match the metatype of the
// argument the method expects. In order to work around it, we specialize
// qMetaTypeInterfaceForType() and produce a "correct" metatype this way.
class Dummy_QMLTYPE_0;
// We set this to the actual value retrieved from an actual instance of the QML
// type before retrieving the metatype interface for the first time.
static const QtPrivate::QMetaTypeInterface *dummyMetaTypeInterface = nullptr;
template<>
const QtPrivate::QMetaTypeInterface *QtPrivate::qMetaTypeInterfaceForType<Dummy_QMLTYPE_0 *>() {
return dummyMetaTypeInterface;
}
static void checkColorProperties(QQmlComponent *component)
{
QVERIFY2(component->isReady(), qPrintable(component->errorString()));
@ -1763,32 +1743,65 @@ void tst_QmlCppCodegen::funcWithParams()
QCOMPARE(object->property("bar").toInt(), 30);
}
// QML-generated types have no C++ names, but we want to call a method that
// expects a pointer to a QML-generated type as argument.
//
// We force the QML engine to assign a specific name to our type and declare
// an incomplete dummy class of the same name here. The dummy class does not
// have a proper metatype by itself. Therefore, when we want to pass a (null)
// pointer of it to invokeMethod(), usually invokeMethod() would complain that
// the metatype of the argument we pass does not match the metatype of the
// argument the method expects. In order to work around it, we specialize
// qMetaTypeInterfaceForType() and produce a "correct" metatype this way.
class Dummy2_QMLTYPE_0;
// We set this to the actual value retrieved from an actual instance of the QML
// type before retrieving the metatype interface for the first time.
static const QtPrivate::QMetaTypeInterface *dummyMetaTypeInterface = nullptr;
template<>
const QtPrivate::QMetaTypeInterface *QtPrivate::qMetaTypeInterfaceForType<Dummy2_QMLTYPE_0 *>() {
return dummyMetaTypeInterface;
}
void tst_QmlCppCodegen::functionArguments()
{
QQmlEngine engine;
qmlClearTypeRegistrations();
// Ensure that Dummy gets counter value 0. Don't do that at home
QQmlEngine engine;
QQmlComponent preheat(&engine);
preheat.setData(R"(
import QtQml
import TestTypes
QtObject {
objectName: Style.objectName
}
)", QUrl(u"qrc:/qt/qml/TestTypes/preheat.qml"_s));
QVERIFY2(preheat.isReady(), qPrintable(preheat.errorString()));
QScopedPointer<QObject> hot(preheat.create());
QVERIFY(!hot.isNull());
// Ensure that Dummy gets counter value 1. Don't do that at home
QScopedValueRollback<QAtomicInt> rb(QQmlPropertyCacheCreatorBase::classIndexCounter, 0);
QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Dummy.qml"_s));
QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Dummy2.qml"_s));
QVERIFY2(component.isReady(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
const QMetaObject *metaObject = object->metaObject();
dummyMetaTypeInterface = metaObject->metaType().iface();
const QByteArray className = QByteArray(metaObject->className());
QCOMPARE(className, "Dummy_QMLTYPE_0");
QCOMPARE(className, "Dummy2_QMLTYPE_0");
int result;
int a = 1;
bool b = false;
Dummy_QMLTYPE_0 *c = nullptr;
Dummy2_QMLTYPE_0 *c = nullptr;
double d = -1.2;
int e = 3;
metaObject->invokeMethod(
object.data(), "someFunction", Q_RETURN_ARG(int, result),
Q_ARG(int, a), Q_ARG(bool, b), Q_ARG(Dummy_QMLTYPE_0 *, c),
Q_ARG(int, a), Q_ARG(bool, b), Q_ARG(Dummy2_QMLTYPE_0 *, c),
Q_ARG(double, d), Q_ARG(int, e));
QCOMPARE(result, 42);