Add autotest for QImageIO format handler plugins
To confirm the functionality of custom imageformats plugins in Qt image reading, both for supporting new formats and for overriding Qt's builtin formats. Change-Id: I6abafdb47301ad1f35b19951e42b1f3b61fe6ec3 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit 6eefe0ca59dc25f7953b93e8b80c62c78a6ccfde) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>bb10
parent
df743c2164
commit
5de95d3aba
|
|
@ -11,9 +11,22 @@ if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
|||
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE test_data_glob
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
images/*)
|
||||
|
||||
list(APPEND test_data ${test_data_glob})
|
||||
|
||||
add_subdirectory(plugin)
|
||||
|
||||
qt_internal_add_test(tst_qimageiohandler
|
||||
SOURCES
|
||||
tst_qimageiohandler.cpp
|
||||
pluginlog.h
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
TestImagePlugin
|
||||
TESTDATA ${test_data}
|
||||
)
|
||||
|
||||
add_dependencies(tst_qimageiohandler TestImagePlugin)
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
|
|
@ -0,0 +1 @@
|
|||
BLUE
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 71 B |
|
|
@ -0,0 +1 @@
|
|||
green
|
||||
|
|
@ -0,0 +1 @@
|
|||
RED
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 643 B |
|
|
@ -0,0 +1 @@
|
|||
yellow
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright (C) 2024 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## TestImagePlugin:
|
||||
#####################################################################
|
||||
|
||||
qt_add_plugin(TestImagePlugin
|
||||
STATIC
|
||||
OUTPUT_NAME qtestimageplugin
|
||||
PLUGIN_TYPE imageformats
|
||||
main.cpp
|
||||
../pluginlog.h
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(TestImagePlugin)
|
||||
target_link_libraries(TestImagePlugin PRIVATE Qt::Core Qt::Gui)
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <qimageiohandler.h>
|
||||
#include <qcoreapplication.h>
|
||||
#include "../pluginlog.h"
|
||||
|
||||
class TestImagePlugin : public QImageIOPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "plugin.json")
|
||||
|
||||
public:
|
||||
QImageIOPlugin::Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
|
||||
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
|
||||
};
|
||||
|
||||
class MyPngHandler : public QImageIOHandler
|
||||
{
|
||||
public:
|
||||
bool canRead() const override
|
||||
{
|
||||
if (canRead(device())) {
|
||||
setFormat(device()->peek(1).isUpper() ? "png" : "foo");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool read(QImage *image) override
|
||||
{
|
||||
QColor col = QColor::fromString(device()->readAll().simplified());
|
||||
if (col.isValid()) {
|
||||
QImage img(32, 32, QImage::Format_RGB32);
|
||||
img.fill(col);
|
||||
*image = img;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool canRead(QIODevice *device)
|
||||
{
|
||||
return device ? QColor::isValidColorName(device->peek(16).simplified()) : false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
QImageIOPlugin::Capabilities TestImagePlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
if (format == "png" || format == "foo" || format == "gif") {
|
||||
PluginLog::append("formatname-matched");
|
||||
return (format == "gif") ? CanWrite : CanRead;
|
||||
}
|
||||
|
||||
Capabilities cap;
|
||||
if (!format.isEmpty()) {
|
||||
PluginLog::append("formatname-unmatched");
|
||||
return cap;
|
||||
}
|
||||
|
||||
if (!device->isOpen())
|
||||
return cap;
|
||||
|
||||
if (device->isReadable()) {
|
||||
if (MyPngHandler::canRead(device)) {
|
||||
PluginLog::append("contents-matched");
|
||||
cap |= CanRead;
|
||||
} else {
|
||||
PluginLog::append("contents-unmatched");
|
||||
}
|
||||
}
|
||||
|
||||
if (device->isWritable())
|
||||
cap |= CanWrite;
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
QImageIOHandler *TestImagePlugin::create(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
QImageIOHandler *handler = new MyPngHandler;
|
||||
handler->setDevice(device);
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "main.moc"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"Keys": [ "png", "foo", "gif" ],
|
||||
"MimeTypes": [ "image/png", "image/foo", "image/gif" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#ifndef PLUGINLOG_H
|
||||
#define PLUGINLOG_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QVariant>
|
||||
|
||||
class PluginLog {
|
||||
public:
|
||||
static QStringList get() { return qApp->property(testProp).toStringList(); }
|
||||
static void set(const QStringList &log) { qApp->setProperty(testProp, log); }
|
||||
static void clear() { set({}); }
|
||||
static void append(const QString &msg) { set(get() << msg); }
|
||||
static int size() { return get().size(); }
|
||||
static QString item(int index) { return get().value(index); }
|
||||
private:
|
||||
static constexpr auto testProp = "_q_testimageplugin";
|
||||
};
|
||||
|
||||
#endif // PLUGINLOG_H
|
||||
|
|
@ -6,8 +6,11 @@
|
|||
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdebug.h>
|
||||
#include <qhash.h>
|
||||
#include <qimageiohandler.h>
|
||||
#include <qfile.h>
|
||||
#include <qimagereader.h>
|
||||
#include "pluginlog.h"
|
||||
|
||||
class tst_QImageIOHandler : public QObject
|
||||
{
|
||||
|
|
@ -16,9 +19,27 @@ Q_OBJECT
|
|||
public:
|
||||
tst_QImageIOHandler();
|
||||
virtual ~tst_QImageIOHandler();
|
||||
static void initMain()
|
||||
{
|
||||
QHashSeed::setDeterministicGlobalSeed();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void getSetCheck();
|
||||
void hasCustomPluginFormat();
|
||||
void pluginRead_data();
|
||||
void pluginRead();
|
||||
void pluginNoAutoDetection_data();
|
||||
void pluginNoAutoDetection();
|
||||
void pluginDecideFromContent_data();
|
||||
void pluginDecideFromContent();
|
||||
void pluginDetectedFormat_data();
|
||||
void pluginDetectedFormat();
|
||||
void pluginWrongFormat_data();
|
||||
void pluginWrongFormat();
|
||||
private:
|
||||
QString m_prefix;
|
||||
QList<QByteArray> m_supportedReadFormats;
|
||||
};
|
||||
|
||||
class MyImageIOHandler : public QImageIOHandler
|
||||
|
|
@ -31,6 +52,8 @@ public:
|
|||
|
||||
tst_QImageIOHandler::tst_QImageIOHandler()
|
||||
{
|
||||
m_prefix = QFINDTESTDATA("images/");
|
||||
m_supportedReadFormats = QImageReader::supportedImageFormats();
|
||||
}
|
||||
|
||||
tst_QImageIOHandler::~tst_QImageIOHandler()
|
||||
|
|
@ -51,5 +74,185 @@ void tst_QImageIOHandler::getSetCheck()
|
|||
delete var1;
|
||||
}
|
||||
|
||||
Q_IMPORT_PLUGIN(TestImagePlugin)
|
||||
|
||||
void tst_QImageIOHandler::hasCustomPluginFormat()
|
||||
{
|
||||
QVERIFY(m_supportedReadFormats.contains("foo"));
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginRead_data()
|
||||
{
|
||||
QTest::addColumn<QString>("color");
|
||||
QTest::addColumn<QString>("suffix");
|
||||
QTest::addColumn<QStringList>("expectedPluginLog");
|
||||
|
||||
QTest::newRow("testplugin") << "green" << "foo" << QStringList({ "formatname-matched" });
|
||||
QTest::newRow("overridden-builtin") << "red" << "png" << QStringList({ "formatname-matched" });
|
||||
QTest::newRow("builtin") << "black" << "bmp" << QStringList({ "formatname-unmatched" }); //### Should be null
|
||||
QTest::newRow("no-suffix") << "blue" << "" << QStringList({ "contents-matched" });
|
||||
QTest::newRow("wrong-suffix") << "yellow" << "jpg" << QStringList({ "contents-matched" });
|
||||
QTest::newRow("unknown-suffix") << "black" << "bar" << QStringList({ "formatname-unmatched", "contents-unmatched" });
|
||||
if (m_supportedReadFormats.contains("jpeg"))
|
||||
QTest::newRow("wrong-suffix2") << "white" << "foo" << QStringList({ "formatname-matched" });
|
||||
if (m_supportedReadFormats.contains("gif"))
|
||||
QTest::newRow("plugin-writeonly") << "cyan" << "gif" << QStringList();
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginRead()
|
||||
{
|
||||
QFETCH(QString, color);
|
||||
QFETCH(QString, suffix);
|
||||
QFETCH(QStringList, expectedPluginLog);
|
||||
|
||||
PluginLog::clear();
|
||||
QString filePath = m_prefix + color + (suffix.isEmpty() ? "" : "." + suffix);
|
||||
QImage img(filePath);
|
||||
QCOMPARE(PluginLog::size(), expectedPluginLog.size());
|
||||
for (int i = 0; i < PluginLog::size(); i++)
|
||||
QCOMPARE(PluginLog::item(i), expectedPluginLog.value(i));
|
||||
QVERIFY(!img.isNull());
|
||||
QCOMPARE(img.pixelColor(0, 0), QColor(color));
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginNoAutoDetection_data()
|
||||
{
|
||||
QTest::addColumn<QString>("color");
|
||||
QTest::addColumn<QString>("suffix");
|
||||
QTest::addColumn<QStringList>("expectedPluginLog");
|
||||
QTest::addColumn<bool>("expectedSuccess");
|
||||
|
||||
QTest::newRow("testplugin") << "green" << "foo" << QStringList({ "formatname-matched" }) << true;
|
||||
QTest::newRow("overridden-builtin") << "red" << "png" << QStringList({ "formatname-matched" }) << true;
|
||||
QTest::newRow("builtin") << "black" << "bmp" << QStringList() << true;
|
||||
QTest::newRow("no-suffix") << "blue" << "" << QStringList() << false;
|
||||
QTest::newRow("wrong-suffix") << "yellow" << "jpg" << QStringList() << false;
|
||||
QTest::newRow("unknown-suffix") << "black" << "bar" << QStringList() << false;
|
||||
QTest::newRow("wrong-suffix2") << "white" << "foo" << QStringList({ "formatname-matched" }) << false;
|
||||
QTest::newRow("plugin-writeonly") << "cyan" << "gif" << QStringList() << true;
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginNoAutoDetection()
|
||||
{
|
||||
QFETCH(QString, color);
|
||||
QFETCH(QString, suffix);
|
||||
QFETCH(QStringList, expectedPluginLog);
|
||||
QFETCH(bool, expectedSuccess);
|
||||
|
||||
QString filePath = m_prefix + color + (suffix.isEmpty() ? "" : "." + suffix);
|
||||
{
|
||||
// Confirm that the file suffix is ignored, i.e. nothing happens if no format is set
|
||||
PluginLog::clear();
|
||||
QImageReader r(filePath);
|
||||
r.setAutoDetectImageFormat(false);
|
||||
QImage img = r.read();
|
||||
QVERIFY(img.isNull());
|
||||
QCOMPARE(PluginLog::size(), 0);
|
||||
}
|
||||
|
||||
PluginLog::clear();
|
||||
QImageReader r(filePath, suffix.toLatin1());
|
||||
r.setAutoDetectImageFormat(false);
|
||||
QImage img = r.read();
|
||||
|
||||
QCOMPARE(PluginLog::size(), expectedPluginLog.size());
|
||||
for (int i = 0; i < PluginLog::size(); i++)
|
||||
QCOMPARE(PluginLog::item(i), expectedPluginLog.value(i));
|
||||
QCOMPARE(!img.isNull(), expectedSuccess);
|
||||
if (expectedSuccess)
|
||||
QCOMPARE(img.pixelColor(0, 0), QColor(color));
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginDecideFromContent_data()
|
||||
{
|
||||
QTest::addColumn<QString>("color");
|
||||
QTest::addColumn<QString>("suffix");
|
||||
QTest::addColumn<QStringList>("expectedPluginLog");
|
||||
|
||||
QTest::newRow("testplugin") << "green" << "foo" << QStringList({ "contents-matched" });
|
||||
QTest::newRow("overridden-builtin") << "red" << "png" << QStringList({ "contents-matched" });
|
||||
QTest::newRow("builtin") << "black" << "bmp" << QStringList({ "contents-unmatched" });
|
||||
QTest::newRow("no-suffix") << "blue" << "" << QStringList({ "contents-matched" });
|
||||
QTest::newRow("wrong-suffix") << "yellow" << "jpg" << QStringList({ "contents-matched" });
|
||||
QTest::newRow("unknown-suffix") << "black" << "bar" << QStringList({ "contents-unmatched" });
|
||||
if (m_supportedReadFormats.contains("jpeg"))
|
||||
QTest::newRow("wrong-suffix2") << "white" << "foo" << QStringList();
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginDecideFromContent()
|
||||
{
|
||||
QFETCH(QString, color);
|
||||
QFETCH(QString, suffix);
|
||||
QFETCH(QStringList, expectedPluginLog);
|
||||
|
||||
QString filePath = m_prefix + color + (suffix.isEmpty() ? "" : "." + suffix);
|
||||
PluginLog::clear();
|
||||
QImageReader r(filePath, suffix.toLatin1());
|
||||
r.setDecideFormatFromContent(true);
|
||||
QImage img = r.read();
|
||||
|
||||
QCOMPARE(PluginLog::size(), expectedPluginLog.size());
|
||||
for (int i = 0; i < PluginLog::size(); i++)
|
||||
QCOMPARE(PluginLog::item(i), expectedPluginLog.value(i));
|
||||
QVERIFY(!img.isNull());
|
||||
QCOMPARE(img.pixelColor(0, 0), QColor(color));
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginDetectedFormat_data()
|
||||
{
|
||||
QTest::addColumn<QString>("color");
|
||||
QTest::addColumn<QString>("suffix");
|
||||
QTest::addColumn<QString>("fileFormat");
|
||||
|
||||
QTest::newRow("testplugin") << "green" << "foo" << "foo";
|
||||
QTest::newRow("overridden-builtin") << "red" << "png" << "png";
|
||||
QTest::newRow("builtin") << "black" << "bmp" << "bmp";
|
||||
QTest::newRow("no-suffix") << "blue" << "" << "png";
|
||||
QTest::newRow("wrong-suffix") << "yellow" << "jpg" << "foo";
|
||||
QTest::newRow("unknown-suffix") << "black" << "bar" << "bmp";
|
||||
if (m_supportedReadFormats.contains("jpeg"))
|
||||
QTest::newRow("wrong-suffix2") << "white" << "foo" << "jpeg";
|
||||
if (m_supportedReadFormats.contains("gif"))
|
||||
QTest::newRow("plugin-writeonly") << "cyan" << "gif" << "gif";
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginDetectedFormat()
|
||||
{
|
||||
QFETCH(QString, color);
|
||||
QFETCH(QString, suffix);
|
||||
QFETCH(QString, fileFormat);
|
||||
|
||||
QString filePath = m_prefix + color + (suffix.isEmpty() ? "" : "." + suffix);
|
||||
QCOMPARE(QImageReader::imageFormat(filePath), fileFormat.toLatin1());
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginWrongFormat_data()
|
||||
{
|
||||
QTest::addColumn<QString>("color");
|
||||
QTest::addColumn<QString>("suffix");
|
||||
QTest::addColumn<QString>("forceFormat");
|
||||
|
||||
QTest::newRow("testplugin") << "green" << "foo" << "bmp";
|
||||
QTest::newRow("overridden-builtin") << "red" << "png" << "bmp";
|
||||
QTest::newRow("builtin") << "black" << "bmp" << "foo";
|
||||
QTest::newRow("no-suffix") << "blue" << "" << "bmp";
|
||||
QTest::newRow("wrong-suffix") << "yellow" << "jpg" << "bmp";
|
||||
QTest::newRow("unknown-suffix") << "black" << "bar" << "foo";
|
||||
QTest::newRow("wrong-suffix2") << "white" << "foo" << "bmp";
|
||||
}
|
||||
|
||||
void tst_QImageIOHandler::pluginWrongFormat()
|
||||
{
|
||||
QFETCH(QString, color);
|
||||
QFETCH(QString, suffix);
|
||||
QFETCH(QString, forceFormat);
|
||||
|
||||
PluginLog::clear();
|
||||
QString filePath = m_prefix + color + (suffix.isEmpty() ? "" : "." + suffix);
|
||||
QImage img(filePath, forceFormat.toLatin1());
|
||||
QVERIFY(img.isNull());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QImageIOHandler)
|
||||
|
||||
#include "tst_qimageiohandler.moc"
|
||||
|
|
|
|||
Loading…
Reference in New Issue