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>
This commit is contained in:
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)
|
||||
|
BIN
tests/auto/gui/image/qimageiohandler/images/black.bar
Normal file
BIN
tests/auto/gui/image/qimageiohandler/images/black.bar
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
tests/auto/gui/image/qimageiohandler/images/black.bmp
Normal file
BIN
tests/auto/gui/image/qimageiohandler/images/black.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
1
tests/auto/gui/image/qimageiohandler/images/blue
Normal file
1
tests/auto/gui/image/qimageiohandler/images/blue
Normal file
@ -0,0 +1 @@
|
||||
BLUE
|
BIN
tests/auto/gui/image/qimageiohandler/images/cyan.gif
Normal file
BIN
tests/auto/gui/image/qimageiohandler/images/cyan.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 B |
1
tests/auto/gui/image/qimageiohandler/images/green.foo
Normal file
1
tests/auto/gui/image/qimageiohandler/images/green.foo
Normal file
@ -0,0 +1 @@
|
||||
green
|
1
tests/auto/gui/image/qimageiohandler/images/red.png
Normal file
1
tests/auto/gui/image/qimageiohandler/images/red.png
Normal file
@ -0,0 +1 @@
|
||||
RED
|
BIN
tests/auto/gui/image/qimageiohandler/images/white.foo
Normal file
BIN
tests/auto/gui/image/qimageiohandler/images/white.foo
Normal file
Binary file not shown.
After Width: | Height: | Size: 643 B |
1
tests/auto/gui/image/qimageiohandler/images/yellow.jpg
Normal file
1
tests/auto/gui/image/qimageiohandler/images/yellow.jpg
Normal file
@ -0,0 +1 @@
|
||||
yellow
|
17
tests/auto/gui/image/qimageiohandler/plugin/CMakeLists.txt
Normal file
17
tests/auto/gui/image/qimageiohandler/plugin/CMakeLists.txt
Normal file
@ -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)
|
89
tests/auto/gui/image/qimageiohandler/plugin/main.cpp
Normal file
89
tests/auto/gui/image/qimageiohandler/plugin/main.cpp
Normal file
@ -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"
|
4
tests/auto/gui/image/qimageiohandler/plugin/plugin.json
Normal file
4
tests/auto/gui/image/qimageiohandler/plugin/plugin.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"Keys": [ "png", "foo", "gif" ],
|
||||
"MimeTypes": [ "image/png", "image/foo", "image/gif" ]
|
||||
}
|
22
tests/auto/gui/image/qimageiohandler/pluginlog.h
Normal file
22
tests/auto/gui/image/qimageiohandler/pluginlog.h
Normal file
@ -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…
x
Reference in New Issue
Block a user