Skip to content

Commit

Permalink
qt module: add qml module test
Browse files Browse the repository at this point in the history
  • Loading branch information
chubinou committed Dec 16, 2024
1 parent 847f721 commit 2baded3
Show file tree
Hide file tree
Showing 14 changed files with 325 additions and 0 deletions.
5 changes: 5 additions & 0 deletions test cases/frameworks/39 qt qml/Basic.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import QtQuick 2.0

Item {
property int ok: 1
}
5 changes: 5 additions & 0 deletions test cases/frameworks/39 qt qml/Internal.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import QtQuick

Item {
property int ok: 5
}
53 changes: 53 additions & 0 deletions test cases/frameworks/39 qt qml/Main.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import QtQuick
import My.Module1 as M1

Item {
id: root

Component.onCompleted: {
function checkInstance(label, instance, value) {
if (!instance) {
console.log(label, "KO instance is null")
return false
} if (instance.ok !== value) {
console.log(label, "KO got", instance.ok, "expected", value)
return false
} else {
console.log(label, "OK")
return true
}
}

function checkClass(namespace, classname, value) {
let newObject = null;
try {
newObject = Qt.createQmlObject(
"import %1; %2 {}".arg(namespace).arg(classname),
root,
"some path"
)
} catch (e) {
console.log(namespace, classname, "KO failed to instanciate object")
return false
}
return checkInstance("%1 %2".arg(namespace).arg(classname), newObject, value)
}

let ret = true
ret &= checkClass("My.Module1", "Basic", 1);
ret &= checkClass("My.Module1", "Thing", 2);
ret &= checkClass("My.Module1", "QmlCppExposed", 3);
ret &= checkInstance("My.Module1 QmlSingleton", M1.QmlSingleton, 5)

ret &= checkClass("My.Module2", "Thing", 2);
ret &= checkClass("My.Module3", "Basic", 1);
ret &= checkClass("My.Module4", "BasicAliased", 1);
ret &= checkClass("My.Module5", "SubdirHeader", 6);
ret &= checkClass("My.Module6", "Basic", 1);

if (!ret)
Qt.exit(1)
else
Qt.quit()
}
}
25 changes: 25 additions & 0 deletions test cases/frameworks/39 qt qml/QmlCppExposed.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include <QObject>
#include <QQmlEngine>

class QmlCppExposed : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int ok READ getOk WRITE setOk NOTIFY okChanged)

public:
inline int getOk() const { return m_ok; }
inline void setOk(int value) {
if (value == m_ok)
return;
m_ok = value;
emit okChanged();
}

signals:
void okChanged();

private:
int m_ok = 3;
};
25 changes: 25 additions & 0 deletions test cases/frameworks/39 qt qml/QmlCppOtherExposed.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include <QObject>
#include <QQmlEngine>

class QmlCppOtherExposed : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int ok READ getOk WRITE setOk NOTIFY okChanged)

public:
inline int getOk() const { return m_ok; }
inline void setOk(int value) {
if (value == m_ok)
return;
m_ok = value;
emit okChanged();
}

signals:
void okChanged();

private:
int m_ok = 42;
};
31 changes: 31 additions & 0 deletions test cases/frameworks/39 qt qml/QmlMain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>

//extern type registration
extern void qml_register_types_My_Module6();

int main(int argCount, char* argVector[])
{
//register resources from static libraries
Q_INIT_RESOURCE(My_Module6);
Q_INIT_RESOURCE(qmlcache_My_Module6);
qml_register_types_My_Module6();

//don't require a grapical environment to run the test
qputenv("QT_QPA_PLATFORM", "offscreen");

QGuiApplication app(argCount, argVector);
QQmlApplicationEngine engine;

QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, [](QObject *object, const QUrl &url){
if (object == nullptr) {
qFatal("unable to load scene");
}
});

engine.addImportPath("qrc:///qt/qml");
engine.addImportPath("qrc:///test");
engine.load("qrc:///qt/qml/My/Module0/Main.qml");
return app.exec();
}
10 changes: 10 additions & 0 deletions test cases/frameworks/39 qt qml/QmlSingleton.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pragma Singleton
import QtQuick

Item {
property alias ok: sub.ok

Internal {
id: sub
}
}
4 changes: 4 additions & 0 deletions test cases/frameworks/39 qt qml/custom_qmldir
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module My.Module4
prefer :/qt/qml/My/Module4/
BasicAliased 1.0 Basic.qml
Thing 1.0 Thing.qml
5 changes: 5 additions & 0 deletions test cases/frameworks/39 qt qml/custom_qmldir.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/qt/qml/My/Module4">
<file alias="qmldir">custom_qmldir</file>
</qresource>
</RCC>
107 changes: 107 additions & 0 deletions test cases/frameworks/39 qt qml/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
project('qt6 qml build test', 'cpp',
meson_version: '>= 1.7.0',
# Qt6 requires C++ 17 support
default_options : ['cpp_std=c++17']
)

qt_modules = ['Core', 'Gui', 'Qml']

qtdep = dependency('qt6', modules : qt_modules, main : true, private_headers: true, required : false, method : get_option('method'))
if not qtdep.found()
error('MESON_SKIP_TEST qt6 not found.')
endif

qtmodule = import('qt6')

qmlmodule1 = qtmodule.qml_module(
'My.Module1',
version: '1.0',
qml_sources: files('Basic.qml', 'subdir/Thing.qml'),
qml_singletons: files('QmlSingleton.qml'),
qml_internals: files('Internal.qml'),
moc_headers: files('QmlCppExposed.hpp', 'QmlCppOtherExposed.hpp'),
designer_supported: true,
dependencies: [qtdep],
install: true
)

#with a different resource prefix
qmlmodule2 = qtmodule.qml_module(
'My.Module2',
version: '1.0',
qml_sources: files('Basic.qml', 'subdir/Thing.qml'),
resources_prefix: '/test',
dependencies: [qtdep],
)

#build without cachegen
qmlmodule3 = qtmodule.qml_module(
'My.Module3',
version: '1.10.42',
qml_sources: files('Basic.qml', 'subdir/Thing.qml'),
cachegen: false,
dependencies: [qtdep],
)

#build without cachegen
qmlmodule4 = qtmodule.qml_module(
'My.Module4',
qml_sources: files('Basic.qml', 'subdir/Thing.qml'),
generate_qmldir: false,
dependencies: [qtdep],
)

qmlmodule4_res = qtmodule.compile_resources(
name : 'qmlmodule4_resource',
sources : files(['custom_qmldir.qrc']),
method : get_option('method')
)

#a module with only C++ classes
cpponly_module = qtmodule.qml_module(
'My.Module5',
version: '1.0',
moc_headers: files('subdir/SubdirHeader.hpp'),
dependencies: [qtdep],
install: true
)

#module as static library
qmlmodule6 = qtmodule.qml_module(
'My.Module6',
version: '1.0',
qml_sources: files('Basic.qml'),
moc_headers: files('subdir/SubdirHeader.hpp'),
cachegen: true,
dependencies: [qtdep],
)

qmlmodule6_static = static_library(
'Qmlmodule6Lib',
sources: qmlmodule6,
include_directories: include_directories('subdir'),
dependencies: [qtdep],
)

#qml entry point and qmldir dependecies
qmlmodule0 = qtmodule.qml_module(
'My.Module0',
version: '1.0',
qml_sources: files('Main.qml'),
imports: ['QtQuick/2.0', 'My.Module1'],
optional_imports: ['My.Module2/auto'],
dependencies: [qtdep],
)

qmltest = executable(
'qmlmodule',
sources : [
'QmlMain.cpp', qmlmodule0, qmlmodule1, qmlmodule2,
qmlmodule3, qmlmodule4, qmlmodule4_res, cpponly_module
],
link_with : qmlmodule6_static,
dependencies : qtdep,
# headers in subdirectory needs to have their include path explicitly
# added for the code generated by by qmltyperegistrar. see QTBUG-87221
include_directories: include_directories('subdir'),
)
1 change: 1 addition & 0 deletions test cases/frameworks/39 qt qml/meson_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
option('method', type : 'string', value : 'auto', description : 'The method to use to find Qt')
27 changes: 27 additions & 0 deletions test cases/frameworks/39 qt qml/subdir/SubdirHeader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include <QObject>
#include <QQmlEngine>

#include "QmlCppExposed.hpp"

class SubdirHeader : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int ok READ getOk WRITE setOk NOTIFY okChanged)

public:
inline int getOk() const { return m_ok; }
inline void setOk(int value) {
if (value == m_ok)
return;
m_ok = value;
emit okChanged();
}

signals:
void okChanged();

private:
int m_ok = 6;
};
5 changes: 5 additions & 0 deletions test cases/frameworks/39 qt qml/subdir/Thing.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import QtQuick 2.0

Item {
property int ok: 2
}
22 changes: 22 additions & 0 deletions test cases/frameworks/39 qt qml/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"matrix": {
"options": {
"method": [
{ "val": "config-tool" },
{ "val": "qmake" },
{ "val": "pkg-config" }
]
}
},
"installed": [
{"type": "file", "file": "usr/qml/My/Module1/QmlSingleton.qml"},
{"type": "file", "file": "usr/qml/My/Module1/qmldir"},
{"type": "file", "file": "usr/qml/My/Module1/Basic.qml"},
{"type": "file", "file": "usr/qml/My/Module1/Internal.qml"},
{"type": "file", "file": "usr/qml/My/Module1/Thing.qml"},
{"type": "file", "file": "usr/qml/My/Module1/My_Module1.qmltypes"},
{"type": "file", "file": "usr/qml/My/Module5/qmldir"},
{"type": "file", "file": "usr/qml/My/Module5/My_Module5.qmltypes"}
],
"expect_skip_on_jobname": ["cygwin", "msys2", "azure", "bionic", "macos"]
}

0 comments on commit 2baded3

Please sign in to comment.