Warning, file /graphics/krita/sdk/tests/filestest.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #ifndef FILESTEST 0007 #define FILESTEST 0008 0009 #include <testutil.h> 0010 #include "testui.h" 0011 0012 #include <QDir> 0013 0014 #include <kaboutdata.h> 0015 #include <klocalizedstring.h> 0016 #include <kis_debug.h> 0017 0018 #include <KisImportExportManager.h> 0019 0020 #include <KisDocument.h> 0021 #include <KisPart.h> 0022 #include <kis_image.h> 0023 #include <KoColorSpace.h> 0024 #include <KoColorSpaceRegistry.h> 0025 0026 #include <QTemporaryFile> 0027 #include <QFileInfo> 0028 #include <QApplication> 0029 #include <QFile> 0030 #include <QFileDevice> 0031 #include <QIODevice> 0032 0033 #ifdef Q_OS_UNIX 0034 # include <unistd.h> 0035 #endif 0036 0037 namespace TestUtil 0038 { 0039 0040 void testFiles(const QString& _dirname, const QStringList& exclusions, const QString &resultSuffix = QString(), int fuzzy = 0, int maxNumFailingPixels = 0, bool showDebug = true) 0041 { 0042 QDir dirSources(_dirname); 0043 QStringList failuresFileInfo; 0044 QStringList failuresDocImage; 0045 QStringList failuresCompare; 0046 0047 Q_FOREACH (QFileInfo sourceFileInfo, dirSources.entryInfoList()) { 0048 qDebug() << sourceFileInfo.fileName(); 0049 if (exclusions.indexOf(sourceFileInfo.fileName()) > -1) { 0050 continue; 0051 } 0052 if (!sourceFileInfo.isHidden() && !sourceFileInfo.isDir()) { 0053 QFileInfo resultFileInfo(QString(FILES_DATA_DIR) + "/results/" + sourceFileInfo.fileName() + resultSuffix + ".png"); 0054 0055 if (!resultFileInfo.exists()) { 0056 failuresFileInfo << resultFileInfo.fileName(); 0057 continue; 0058 } 0059 0060 KisDocument *doc = qobject_cast<KisDocument*>(KisPart::instance()->createDocument()); 0061 0062 KisImportExportManager manager(doc); 0063 doc->setFileBatchMode(true); 0064 0065 KisImportExportErrorCode status = manager.importDocument(sourceFileInfo.absoluteFilePath(), QString()); 0066 Q_UNUSED(status); 0067 0068 if (!doc->image()) { 0069 failuresDocImage << sourceFileInfo.fileName(); 0070 continue; 0071 } 0072 0073 QString id = doc->image()->colorSpace()->id(); 0074 if (id != "GRAYA" && id != "GRAYAU16" && id != "RGBA" && id != "RGBA16") { 0075 dbgKrita << "Images need conversion"; 0076 doc->image()->convertImageColorSpace(KoColorSpaceRegistry::instance()->rgb8(), 0077 KoColorConversionTransformation::IntentAbsoluteColorimetric, 0078 KoColorConversionTransformation::NoOptimization); 0079 doc->image()->waitForDone(); 0080 } 0081 0082 qApp->processEvents(); 0083 doc->image()->waitForDone(); 0084 QImage sourceImage = doc->image()->projection()->convertToQImage(0, doc->image()->bounds()); 0085 0086 0087 0088 QImage resultImage(resultFileInfo.absoluteFilePath()); 0089 resultImage = resultImage.convertToFormat(QImage::Format_ARGB32); 0090 sourceImage = sourceImage.convertToFormat(QImage::Format_ARGB32); 0091 0092 QPoint pt; 0093 0094 if (!TestUtil::compareQImages(pt, resultImage, sourceImage, fuzzy, fuzzy, maxNumFailingPixels, showDebug)) { 0095 failuresCompare << sourceFileInfo.fileName() + ": " + QString("Pixel (%1,%2) has different values").arg(pt.x()).arg(pt.y()).toLatin1(); 0096 sourceImage.save(sourceFileInfo.fileName() + ".png"); 0097 resultImage.save(resultFileInfo.fileName() + ".expected.png"); 0098 continue; 0099 } 0100 0101 delete doc; 0102 } 0103 } 0104 if (failuresCompare.isEmpty() && failuresDocImage.isEmpty() && failuresFileInfo.isEmpty()) { 0105 return; 0106 } 0107 qWarning() << "Comparison failures: " << failuresCompare; 0108 qWarning() << "No image failures: " << failuresDocImage; 0109 qWarning() << "No comparison image: " << failuresFileInfo; 0110 0111 QFAIL("Failed testing files"); 0112 } 0113 0114 0115 void prepareFile(QFileInfo sourceFileInfo, bool removePermissionToWrite, bool removePermissionToRead) 0116 { 0117 0118 QFileDevice::Permissions permissionsBefore; 0119 if (sourceFileInfo.exists()) { 0120 permissionsBefore = QFile::permissions(sourceFileInfo.absoluteFilePath()); 0121 ENTER_FUNCTION() << permissionsBefore; 0122 } else { 0123 QFile file(sourceFileInfo.absoluteFilePath()); 0124 bool opened = file.open(QIODevice::ReadWrite); 0125 if (!opened) { 0126 qDebug() << "The file cannot be opened/created: " << file.error() << file.errorString(); 0127 } 0128 permissionsBefore = file.permissions(); 0129 file.close(); 0130 } 0131 QFileDevice::Permissions permissionsNow = permissionsBefore; 0132 if (removePermissionToRead) { 0133 permissionsNow = permissionsBefore & 0134 (~QFileDevice::ReadUser & ~QFileDevice::ReadOwner 0135 & ~QFileDevice::ReadGroup & ~QFileDevice::ReadOther); 0136 } 0137 if (removePermissionToWrite) { 0138 permissionsNow = permissionsBefore & 0139 (~QFileDevice::WriteUser & ~QFileDevice::WriteOwner 0140 & ~QFileDevice::WriteGroup & ~QFileDevice::WriteOther); 0141 } 0142 0143 bool success = QFile::setPermissions(sourceFileInfo.absoluteFilePath(), permissionsNow); 0144 if (!success) { 0145 qWarning() << "prepareFile(): Failed to set permission of file" << sourceFileInfo.absoluteFilePath() 0146 << "from" << permissionsBefore << "to" << permissionsNow; 0147 } 0148 } 0149 0150 void restorePermissionsToReadAndWrite(QFileInfo sourceFileInfo) 0151 { 0152 QFileDevice::Permissions permissionsNow = sourceFileInfo.permissions(); 0153 QFileDevice::Permissions permissionsAfter = permissionsNow 0154 | (QFileDevice::ReadUser | QFileDevice::ReadOwner 0155 | QFileDevice::ReadGroup | QFileDevice::ReadOther) 0156 | (QFileDevice::WriteUser | QFileDevice::WriteOwner 0157 | QFileDevice::WriteGroup | QFileDevice::WriteOther); 0158 bool success = QFile::setPermissions(sourceFileInfo.absoluteFilePath(), permissionsAfter); 0159 if (!success) { 0160 qWarning() << "restorePermissionsToReadAndWrite(): Failed to set permission of file" << sourceFileInfo.absoluteFilePath() 0161 << "from" << permissionsNow << "to" << permissionsAfter; 0162 } 0163 } 0164 0165 const QString &impexTempFilesDir() { 0166 static const QString s_path = []() { 0167 const QString path = QDir::cleanPath( 0168 QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/impex_test") + '/'; 0169 QDir(path).mkpath(QStringLiteral(".")); 0170 return path; 0171 }(); 0172 return s_path; 0173 } 0174 0175 0176 void testImportFromWriteonly(QString mimetype) 0177 { 0178 #ifdef Q_OS_WIN 0179 /// on Windows one cannot create a write-only file, so just skip this test 0180 /// (but keep it compiled to avoid compilation issues) 0181 QSKIP("Cannot test write-only file on Windows."); 0182 #endif 0183 0184 #ifdef Q_OS_UNIX 0185 if (geteuid() == 0) { 0186 QSKIP("Test is being run as root; removing read permission has no effect."); 0187 } 0188 #endif 0189 0190 QString writeonlyFilename = impexTempFilesDir() + "writeonlyFile.txt"; 0191 QFileInfo sourceFileInfo(writeonlyFilename); 0192 0193 prepareFile(sourceFileInfo, false, true); 0194 0195 KisDocument *doc = qobject_cast<KisDocument*>(KisPart::instance()->createDocument()); 0196 0197 KisImportExportManager manager(doc); 0198 doc->setFileBatchMode(true); 0199 0200 KisImportExportErrorCode status = manager.importDocument(sourceFileInfo.absoluteFilePath(), mimetype); 0201 qDebug() << "import result = " << status; 0202 0203 QString failMessage = ""; 0204 bool fail = false; 0205 0206 if (status == ImportExportCodes::FileFormatIncorrect) { 0207 qDebug() << "Make sure you set the correct mimetype in the test case."; 0208 failMessage = "Incorrect status."; 0209 fail = true; 0210 } 0211 0212 qApp->processEvents(); 0213 0214 if (doc->image()) { 0215 doc->image()->waitForDone(); 0216 } 0217 0218 delete doc; 0219 0220 if (fail || status.isOk()) { 0221 qDebug() << "The file permission is:" << QFile::permissions(sourceFileInfo.absoluteFilePath()); 0222 } 0223 0224 restorePermissionsToReadAndWrite(sourceFileInfo); 0225 0226 QVERIFY(!status.isOk()); 0227 if (fail) { 0228 QFAIL(failMessage.toUtf8()); 0229 } 0230 0231 } 0232 0233 0234 void testExportToReadonly(QString mimetype) 0235 { 0236 #ifdef Q_OS_UNIX 0237 if (geteuid() == 0) { 0238 QSKIP("Test is being run as root; removing write permission has no effect."); 0239 } 0240 #endif 0241 0242 QString readonlyFilename = impexTempFilesDir() + "readonlyFile.txt"; 0243 0244 QFileInfo sourceFileInfo(readonlyFilename); 0245 prepareFile(sourceFileInfo, true, false); 0246 0247 KisDocument *doc = qobject_cast<KisDocument*>(KisPart::instance()->createDocument()); 0248 0249 KisImportExportManager manager(doc); 0250 doc->setFileBatchMode(true); 0251 0252 KisImportExportErrorCode status = ImportExportCodes::OK; 0253 QString failMessage = ""; 0254 bool fail = false; 0255 0256 { 0257 MaskParent p; 0258 ENTER_FUNCTION() << doc->image(); 0259 0260 doc->setCurrentImage(p.image); 0261 0262 bool result = doc->exportDocumentSync(sourceFileInfo.absoluteFilePath(), mimetype.toUtf8()); 0263 status = result ? ImportExportCodes::OK : ImportExportCodes::Failure; 0264 0265 qDebug() << "export result = " << status; 0266 0267 qApp->processEvents(); 0268 0269 if (doc->image()) { 0270 doc->image()->waitForDone(); 0271 } 0272 0273 } 0274 delete doc; 0275 0276 if (status.isOk()) { 0277 qDebug() << "The file permission is:" << QFile::permissions(sourceFileInfo.absoluteFilePath()); 0278 } 0279 0280 restorePermissionsToReadAndWrite(sourceFileInfo); 0281 0282 QVERIFY(!status.isOk()); 0283 if (fail) { 0284 QFAIL(failMessage.toUtf8()); 0285 } 0286 } 0287 0288 0289 0290 void testImportIncorrectFormat(QString mimetype) 0291 { 0292 QString incorrectFormatFilename = impexTempFilesDir() + "incorrectFormatFile.txt"; 0293 QFileInfo sourceFileInfo(incorrectFormatFilename); 0294 0295 prepareFile(sourceFileInfo, false, false); 0296 0297 KisDocument *doc = qobject_cast<KisDocument*>(KisPart::instance()->createDocument()); 0298 0299 KisImportExportManager manager(doc); 0300 doc->setFileBatchMode(true); 0301 0302 KisImportExportErrorCode status = manager.importDocument(sourceFileInfo.absoluteFilePath(), mimetype); 0303 qDebug() << "import result = " << status; 0304 0305 qApp->processEvents(); 0306 0307 if (doc->image()) { 0308 doc->image()->waitForDone(); 0309 } 0310 0311 delete doc; 0312 0313 QVERIFY(!status.isOk()); 0314 QVERIFY(status == KisImportExportErrorCode(ImportExportCodes::FileFormatIncorrect) 0315 || status == KisImportExportErrorCode(ImportExportCodes::ErrorWhileReading)); // in case the filter doesn't know if it can't read or just parse 0316 0317 } 0318 0319 0320 void testExportToColorSpace(QString mimetype, const KoColorSpace* space, KisImportExportErrorCode expected) 0321 { 0322 QString colorspaceFilename = impexTempFilesDir() + "colorspace.txt"; 0323 0324 QFileInfo sourceFileInfo(colorspaceFilename); 0325 prepareFile(sourceFileInfo, true, true); 0326 restorePermissionsToReadAndWrite(sourceFileInfo); 0327 0328 KisDocument *doc = qobject_cast<KisDocument*>(KisPart::instance()->createDocument()); 0329 0330 KisImportExportManager manager(doc); 0331 doc->setFileBatchMode(true); 0332 0333 KisImportExportErrorCode statusExport = ImportExportCodes::OK; 0334 KisImportExportErrorCode statusImport = ImportExportCodes::OK; 0335 0336 QString failMessage = ""; 0337 bool fail = false; 0338 0339 { 0340 MaskParent p; 0341 0342 doc->setCurrentImage(p.image); 0343 doc->image()->convertImageColorSpace(space, KoColorConversionTransformation::Intent::IntentPerceptual, KoColorConversionTransformation::ConversionFlag::Empty); 0344 doc->image()->waitForDone(); 0345 0346 bool result = doc->exportDocumentSync(QString(colorspaceFilename), mimetype.toUtf8()); 0347 statusExport = result ? ImportExportCodes::OK : ImportExportCodes::Failure; 0348 0349 statusImport = manager.importDocument(colorspaceFilename, mimetype.toUtf8()); 0350 if (!(statusImport == ImportExportCodes::OK)) { 0351 fail = true; 0352 failMessage = "Incorrect status"; 0353 } 0354 0355 bool mismatch = (*(doc->image()->colorSpace()) != *space) || (doc->image()->colorSpace()->profile() != space->profile()); 0356 if (mismatch) { 0357 qDebug() << "Document color space = " << (doc->image()->colorSpace())->id(); 0358 qDebug() << "Saved color space = " << space->id(); 0359 fail = true; 0360 failMessage = "Mismatch of color spaces"; 0361 } 0362 0363 qApp->processEvents(); 0364 0365 if (doc->image()) { 0366 doc->image()->waitForDone(); 0367 } 0368 0369 } 0370 delete doc; 0371 0372 QFile::remove(colorspaceFilename); 0373 0374 if (fail) { 0375 QFAIL(failMessage.toUtf8()); 0376 } 0377 0378 QVERIFY(statusExport.isOk()); 0379 QVERIFY(statusExport == expected); 0380 } 0381 0382 0383 0384 0385 0386 0387 } 0388 #endif