File indexing completed on 2024-05-12 05:10:01
0001 /*************************************************************************** 0002 Copyright (C) 2017 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include <config.h> 0026 #include "imagejobtest.h" 0027 0028 #include "../images/imagejob.h" 0029 #include "../images/imagefactory.h" 0030 #include "../images/imageinfo.h" 0031 0032 #include <KLocalizedString> 0033 0034 #include <QTest> 0035 #include <QEventLoop> 0036 #include <QTemporaryFile> 0037 #include <QNetworkInterface> 0038 #include <QSignalSpy> 0039 #include <QStandardPaths> 0040 0041 QTEST_GUILESS_MAIN( ImageJobTest ) 0042 0043 static bool hasNetwork() { 0044 #ifdef ENABLE_NETWORK_TESTS 0045 foreach(const QNetworkInterface& net, QNetworkInterface::allInterfaces()) { 0046 if(net.flags().testFlag(QNetworkInterface::IsUp) && !net.flags().testFlag(QNetworkInterface::IsLoopBack)) { 0047 return true; 0048 } 0049 } 0050 #endif 0051 return false; 0052 } 0053 0054 void ImageJobTest::initTestCase() { 0055 QStandardPaths::setTestModeEnabled(true); 0056 KLocalizedString::setApplicationDomain("tellico"); 0057 Tellico::ImageFactory::init(); 0058 } 0059 0060 void ImageJobTest::cleanupTestCase() { 0061 } 0062 0063 void ImageJobTest::init() { 0064 m_result = -1; 0065 m_imageId.clear(); 0066 } 0067 0068 void ImageJobTest::enterLoop() { 0069 QEventLoop eventLoop; 0070 connect(this, &ImageJobTest::exitLoop, &eventLoop, &QEventLoop::quit); 0071 eventLoop.exec(QEventLoop::ExcludeUserInputEvents); 0072 } 0073 0074 void ImageJobTest::slotGetResult(KJob* job) { 0075 m_result = job->error(); 0076 if(m_result > 1 && !job->errorString().isEmpty()) qDebug() << job->errorString(); 0077 emit exitLoop(); 0078 } 0079 0080 void ImageJobTest::slotAvailable(const QString& id_) { 0081 m_result = 0; 0082 m_imageId = id_; 0083 emit exitLoop(); 0084 } 0085 0086 void ImageJobTest::testInvalidUrl() { 0087 QUrl u; 0088 0089 Tellico::ImageJob* job = new Tellico::ImageJob(u); 0090 connect(job, &KJob::result, 0091 this, &ImageJobTest::slotGetResult); 0092 0093 enterLoop(); 0094 QCOMPARE(m_result, int(KIO::ERR_MALFORMED_URL)); 0095 } 0096 0097 void ImageJobTest::testNonexistant() { 0098 QUrl u(QStringLiteral("file:///non-existent-location")); 0099 0100 Tellico::ImageJob* job = new Tellico::ImageJob(u); 0101 connect(job, &KJob::result, 0102 this, &ImageJobTest::slotGetResult); 0103 0104 enterLoop(); 0105 QCOMPARE(m_result, int(KIO::ERR_CANNOT_OPEN_FOR_READING)); 0106 } 0107 0108 void ImageJobTest::testUnreadable() { 0109 QTemporaryFile tmpFile; 0110 QVERIFY(tmpFile.open()); 0111 QVERIFY(!tmpFile.fileName().isEmpty()); 0112 QVERIFY(tmpFile.setPermissions(QFileDevice::Permissions())); 0113 tmpFile.close(); 0114 QVERIFY(!tmpFile.isReadable()); 0115 QUrl u = QUrl::fromLocalFile(tmpFile.fileName()); 0116 0117 Tellico::ImageJob* job = new Tellico::ImageJob(u); 0118 connect(job, &KJob::result, 0119 this, &ImageJobTest::slotGetResult); 0120 0121 enterLoop(); 0122 // on the gitlab CI, QFileInfo(tmpFile).isReadable can still return true 0123 // so check for either result code 0124 QVERIFY(m_result == KIO::ERR_CANNOT_OPEN_FOR_READING || 0125 m_result == KIO::ERR_UNKNOWN); 0126 0127 const Tellico::Data::Image& img = job->image(); 0128 QVERIFY(img.isNull()); 0129 } 0130 0131 void ImageJobTest::testImageInvalid() { 0132 // text file is an invalid image 0133 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("imagejobtest.cpp")); 0134 0135 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0136 connect(job.data(), &KJob::result, 0137 this, &ImageJobTest::slotGetResult); 0138 0139 enterLoop(); 0140 QCOMPARE(m_result, int(KIO::ERR_UNKNOWN)); 0141 0142 const Tellico::Data::Image& img = job->image(); 0143 QVERIFY(img.isNull()); 0144 QCOMPARE(img.linkOnly(), false); 0145 } 0146 0147 void ImageJobTest::testImageLoad() { 0148 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0149 0150 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0151 connect(job.data(), &KJob::result, 0152 this, &ImageJobTest::slotGetResult); 0153 0154 enterLoop(); 0155 // success! 0156 QCOMPARE(m_result, 0); 0157 0158 const Tellico::Data::Image& img = job->image(); 0159 QVERIFY(!img.isNull()); 0160 QCOMPARE(img.id(), QStringLiteral("dde5bf2cbd90fad8635a26dfb362e0ff.png")); 0161 QCOMPARE(img.format(), QByteArray("png")); 0162 QCOMPARE(img.linkOnly(), false); 0163 0164 // check that the job is automatically deleted 0165 qApp->processEvents(); 0166 QVERIFY(!job); 0167 } 0168 0169 void ImageJobTest::testImageLoadWithId() { 0170 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0171 0172 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u, QStringLiteral("tellico-rocks")); 0173 connect(job.data(), &KJob::result, 0174 this, &ImageJobTest::slotGetResult); 0175 0176 enterLoop(); 0177 // success! 0178 QCOMPARE(m_result, 0); 0179 0180 const Tellico::Data::Image& img = job->image(); 0181 QVERIFY(!img.isNull()); 0182 QCOMPARE(img.id(), QStringLiteral("tellico-rocks")); 0183 QCOMPARE(img.format(), QByteArray("png")); 0184 QCOMPARE(img.linkOnly(), false); 0185 } 0186 0187 void ImageJobTest::testImageLink() { 0188 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0189 0190 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u, 0191 QString() /* id */, 0192 false /* quiet */); 0193 job->setLinkOnly(true); 0194 connect(job.data(), &KJob::result, 0195 this, &ImageJobTest::slotGetResult); 0196 0197 enterLoop(); 0198 // success! 0199 QCOMPARE(m_result, 0); 0200 0201 const Tellico::Data::Image& img = job->image(); 0202 QVERIFY(!img.isNull()); 0203 // id is not the MD5 hash 0204 QVERIFY(img.id() != QStringLiteral("dde5bf2cbd90fad8635a26dfb362e0ff.png")); 0205 QCOMPARE(img.format(), QByteArray("png")); 0206 QCOMPARE(img.linkOnly(), true); 0207 } 0208 0209 void ImageJobTest::testNetworkImage() { 0210 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0211 0212 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0213 0214 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0215 connect(job.data(), &KJob::result, 0216 this, &ImageJobTest::slotGetResult); 0217 0218 enterLoop(); 0219 // success! 0220 QCOMPARE(m_result, 0); 0221 0222 const Tellico::Data::Image& img = job->image(); 0223 QVERIFY(!img.isNull()); 0224 QCOMPARE(img.id(), QStringLiteral("ecaf5185c4016881aaabb4933211d5d6.png")); 0225 QCOMPARE(img.format(), QByteArray("png")); 0226 QCOMPARE(img.linkOnly(), false); 0227 0228 // check that the job is automatically deleted 0229 qApp->processEvents(); 0230 QVERIFY(!job); 0231 } 0232 0233 void ImageJobTest::testNetworkImageLink() { 0234 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0235 0236 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0237 0238 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u, 0239 QString() /* id */, 0240 false /* quiet */); 0241 job->setLinkOnly(true); 0242 connect(job.data(), &KJob::result, 0243 this, &ImageJobTest::slotGetResult); 0244 0245 enterLoop(); 0246 // success! 0247 QCOMPARE(m_result, 0); 0248 0249 const Tellico::Data::Image& img = job->image(); 0250 QVERIFY(!img.isNull()); 0251 QCOMPARE(img.id(), u.url()); 0252 QCOMPARE(img.format(), QByteArray("png")); 0253 QCOMPARE(img.linkOnly(), true); 0254 } 0255 0256 void ImageJobTest::testNetworkImageInvalid() { 0257 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0258 0259 QUrl u(QStringLiteral("https://tellico-project.org")); 0260 0261 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0262 connect(job.data(), &KJob::result, 0263 this, &ImageJobTest::slotGetResult); 0264 0265 enterLoop(); 0266 QCOMPARE(m_result, int(KIO::ERR_UNKNOWN)); 0267 0268 const Tellico::Data::Image& img = job->image(); 0269 QVERIFY(img.isNull()); 0270 } 0271 0272 void ImageJobTest::testFactoryRequestLocal() { 0273 QVERIFY(m_imageId.isEmpty()); 0274 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0275 this, &ImageJobTest::slotAvailable); 0276 0277 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0278 Tellico::ImageFactory::requestImageById(u.url()); 0279 0280 // don't need to enter loop since the image is local and signal fires immediately 0281 QVERIFY(!m_imageId.isEmpty()); 0282 // success! 0283 QCOMPARE(m_result, 0); 0284 0285 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0286 QVERIFY(!img.isNull()); 0287 // id is not the MD5 hash 0288 QVERIFY(img.id() != QStringLiteral("dde5bf2cbd90fad8635a26dfb362e0ff.png")); 0289 QCOMPARE(img.format(), QByteArray("png")); 0290 QCOMPARE(img.linkOnly(), true); 0291 } 0292 0293 void ImageJobTest::testFactoryRequestLocalInvalid() { 0294 QVERIFY(m_imageId.isEmpty()); 0295 QSignalSpy spy(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable); 0296 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0297 this, &ImageJobTest::slotAvailable); 0298 0299 // text file is an invalid image 0300 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("imagejobtest.cpp")); 0301 Tellico::ImageFactory::requestImageById(u.url()); 0302 0303 // it will be a null image, but a local url, so image is still loaded with immediate signal 0304 QCOMPARE(spy.count(), 1); 0305 // the available image id is the url 0306 QCOMPARE(m_imageId, u.url()); 0307 0308 // now try to load it 0309 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0310 QVERIFY(img.isNull()); 0311 QCOMPARE(img.linkOnly(), false); 0312 // make sure the null image list is updated 0313 QVERIFY(Tellico::ImageFactory::self()->hasNullImage(m_imageId)); 0314 // the image should not be in local memory now 0315 QVERIFY(!Tellico::ImageFactory::self()->hasImageInMemory(m_imageId)); 0316 QVERIFY(!Tellico::ImageFactory::self()->hasImageInfo(m_imageId)); 0317 } 0318 0319 void ImageJobTest::testFactoryRequestNetwork() { 0320 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0321 0322 QVERIFY(m_imageId.isEmpty()); 0323 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0324 this, &ImageJobTest::slotAvailable); 0325 0326 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0327 Tellico::ImageFactory::requestImageById(u.url()); 0328 0329 enterLoop(); 0330 QVERIFY(!m_imageId.isEmpty()); 0331 // success! 0332 QCOMPARE(m_result, 0); 0333 // the image should be in local memory now 0334 QVERIFY(Tellico::ImageFactory::self()->hasImageInMemory(m_imageId)); 0335 QVERIFY(Tellico::ImageFactory::self()->hasImageInfo(m_imageId)); 0336 0337 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0338 QVERIFY(!img.isNull()); 0339 // id is the MD5 hash, since it's not link only 0340 QCOMPARE(img.id(), QStringLiteral("ecaf5185c4016881aaabb4933211d5d6.png")); 0341 QCOMPARE(img.format(), QByteArray("png")); 0342 QCOMPARE(img.linkOnly(), false); 0343 } 0344 0345 void ImageJobTest::testFactoryRequestNetworkLinkOnly() { 0346 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0347 0348 QVERIFY(m_imageId.isEmpty()); 0349 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0350 this, &ImageJobTest::slotAvailable); 0351 0352 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0353 // first, tell the image factory that the image is link only 0354 Tellico::Data::ImageInfo info(u.url(), "PNG", 64, 64, true /* link only */); 0355 Tellico::ImageFactory::cacheImageInfo(info); 0356 0357 Tellico::ImageFactory::requestImageById(u.url()); 0358 0359 enterLoop(); 0360 QVERIFY(!m_imageId.isEmpty()); 0361 // success! 0362 QCOMPARE(m_result, 0); 0363 // the image should be in local memory now 0364 QVERIFY(Tellico::ImageFactory::self()->hasImageInMemory(m_imageId)); 0365 QVERIFY(Tellico::ImageFactory::self()->hasImageInfo(m_imageId)); 0366 0367 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0368 QVERIFY(!img.isNull()); 0369 // id is not the MD5 hash 0370 QCOMPARE(img.id(), u.url()); 0371 QCOMPARE(img.format(), QByteArray("png")); 0372 QCOMPARE(img.linkOnly(), true); 0373 }