Revision control

Copy as Markdown

// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QTest>
#include <QtTest/QSignalSpy>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdiriterator.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuickVectorImage/private/qquickvectorimage_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
class tst_VectorImage : public QQmlDataTest
{
Q_OBJECT
public:
tst_VectorImage();
private slots:
void parseFiles_data();
void parseFiles();
void parseBrokenFile();
void parseNoAssumeTrustedSource();
void renderFiles_data();
void renderFiles();
};
tst_VectorImage::tst_VectorImage()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
}
void tst_VectorImage::parseFiles_data()
{
QTest::addColumn<QString>("fileName");
{
QDirIterator it(QStringLiteral(":/json"),
{ QStringLiteral("*.json") });
QVERIFY(it.hasNext());
while (it.hasNext()) {
QFileInfo info(it.next());
QString fileName = info.fileName();
QByteArray rowName = fileName.toUtf8();
QTest::newRow(rowName) << fileName;
}
}
{
QDirIterator it(QStringLiteral(":/json/precomp"),
{ QStringLiteral("*.json") });
QVERIFY(it.hasNext());
while (it.hasNext()) {
QFileInfo info(it.next());
QString fileName = QStringLiteral("precomp/") + info.fileName();
QByteArray rowName = fileName.toUtf8();
QTest::newRow(rowName) << fileName;
}
}
{
QDirIterator it(QStringLiteral(":/json/mod"),
{ QStringLiteral("*.json") });
QVERIFY(it.hasNext());
while (it.hasNext()) {
QFileInfo info(it.next());
QString fileName = QStringLiteral("mod/") + info.fileName();
QByteArray rowName = fileName.toUtf8();
QTest::newRow(rowName) << fileName;
}
}
}
void tst_VectorImage::parseFiles()
{
QFETCH(QString, fileName);
QQmlEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("fileName"), QStringLiteral("qrc:/json/%1").arg(fileName));
QQmlComponent c(&engine, testFileUrl("vectorimage.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
std::unique_ptr<QObject> object(c.create());
QQuickVectorImage *item = qobject_cast<QQuickVectorImage *>(object.get());
QVERIFY(item != nullptr);
QVERIFY(!item->childItems().isEmpty());
QVERIFY(!item->childItems().first()->size().isNull());
QCOMPARE(item->status(), QQuickVectorImage::Status::Ready);
}
void tst_VectorImage::parseBrokenFile()
{
QQmlEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("fileName"), testFileUrl("json/broken.json"));
QQmlComponent c(&engine, testFileUrl("vectorimage.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
std::unique_ptr<QObject> object(c.create());
QQuickVectorImage *item = qobject_cast<QQuickVectorImage *>(object.get());
QVERIFY(item != nullptr);
QVERIFY(item->childItems().isEmpty());
QCOMPARE(item->status(), QQuickVectorImage::Status::Error);
}
void tst_VectorImage::parseNoAssumeTrustedSource()
{
QQmlEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("fileName"), testFileUrl("json/ok.json"));
{
QQmlComponent c(&engine, testFileUrl("vectorimage.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
std::unique_ptr<QObject> object(c.create());
QQuickVectorImage *item = qobject_cast<QQuickVectorImage *>(object.get());
QVERIFY(item != nullptr);
QVERIFY(!item->childItems().isEmpty());
QVERIFY(!item->childItems().first()->size().isNull());
QCOMPARE(item->status(), QQuickVectorImage::Status::Ready);
}
{
QQmlComponent c(&engine, testFileUrl("vectorimage_noassumetrustedsource.qml"));
QQuickVectorImage *item = qobject_cast<QQuickVectorImage *>(c.create());
auto cleanup = qScopeGuard([&item] {
delete item;
item = nullptr;
});
QVERIFY(item != nullptr);
QVERIFY(item->childItems().isEmpty());
QCOMPARE(item->status(), QQuickVectorImage::Status::Error);
}
}
void tst_VectorImage::renderFiles_data()
{
QTest::addColumn<QUrl>("fileName");
QTest::newRow("assert_qlottiestroke.json") << testFileUrl("json/assert_qlottiestroke.json");
QTest::newRow("crash_qlottielayer_updateproperties.json") << testFileUrl("json/crash_qlottielayer_updateproperties.json");
QTest::newRow("crash_qlottieprecomplayer_updateproperties.json") << testFileUrl("json/crash_qlottieprecomplayer_updateproperties.json");
QTest::newRow("crash_qlottiegroup_children.json") << testFileUrl("json/crash_qlottiegroup_children.json");
QTest::newRow("crash_qlottiegradientholder_gradient.json") << testFileUrl("json/crash_qlottiegradientholder_gradient.json");
QTest::newRow("crash_qlottiegradientholder_colorstops.json") << testFileUrl("json/crash_qlottiegradientholder_colorstops.json");
QTest::newRow("crash_qlottiegradientholder_colorstops_negative.json") << testFileUrl("json/crash_qlottiegradientholder_colorstops_negative.json");
}
void tst_VectorImage::renderFiles()
{
QFETCH(QUrl, fileName);
QQmlEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("fileName"), fileName);
QQuickWindow window;
window.resize(512, 512);
window.create();
QQmlComponent c(&engine, testFileUrl("vectorimage.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
std::unique_ptr<QObject> object(c.create());
QQuickVectorImage *item = qobject_cast<QQuickVectorImage *>(object.get());
QVERIFY(item != nullptr);
item->setParentItem(window.contentItem());
window.grabWindow();
}
QTEST_MAIN(tst_VectorImage)
#include "tst_vectorimage.moc"