File indexing completed on 2024-05-12 16:46:19
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 <QTest> 0033 #include <QEventLoop> 0034 #include <QTemporaryFile> 0035 #include <QNetworkInterface> 0036 #include <QSignalSpy> 0037 #include <QStandardPaths> 0038 0039 QTEST_GUILESS_MAIN( ImageJobTest ) 0040 0041 static bool hasNetwork() { 0042 #ifdef ENABLE_NETWORK_TESTS 0043 foreach(const QNetworkInterface& net, QNetworkInterface::allInterfaces()) { 0044 if(net.flags().testFlag(QNetworkInterface::IsUp) && !net.flags().testFlag(QNetworkInterface::IsLoopBack)) { 0045 return true; 0046 } 0047 } 0048 #endif 0049 return false; 0050 } 0051 0052 void ImageJobTest::initTestCase() { 0053 QStandardPaths::setTestModeEnabled(true); 0054 Tellico::ImageFactory::init(); 0055 } 0056 0057 void ImageJobTest::cleanupTestCase() { 0058 } 0059 0060 void ImageJobTest::init() { 0061 m_result = -1; 0062 m_imageId.clear(); 0063 } 0064 0065 void ImageJobTest::enterLoop() { 0066 QEventLoop eventLoop; 0067 connect(this, &ImageJobTest::exitLoop, &eventLoop, &QEventLoop::quit); 0068 eventLoop.exec(QEventLoop::ExcludeUserInputEvents); 0069 } 0070 0071 void ImageJobTest::slotGetResult(KJob* job) { 0072 m_result = job->error(); 0073 emit exitLoop(); 0074 } 0075 0076 void ImageJobTest::slotAvailable(const QString& id_) { 0077 m_result = 0; 0078 m_imageId = id_; 0079 emit exitLoop(); 0080 } 0081 0082 void ImageJobTest::testInvalidUrl() { 0083 QUrl u; 0084 0085 Tellico::ImageJob* job = new Tellico::ImageJob(u); 0086 connect(job, &KJob::result, 0087 this, &ImageJobTest::slotGetResult); 0088 0089 enterLoop(); 0090 QCOMPARE(m_result, int(KIO::ERR_MALFORMED_URL)); 0091 } 0092 0093 void ImageJobTest::testNonexistant() { 0094 QUrl u(QStringLiteral("file:///non-existent-location")); 0095 0096 Tellico::ImageJob* job = new Tellico::ImageJob(u); 0097 connect(job, &KJob::result, 0098 this, &ImageJobTest::slotGetResult); 0099 0100 enterLoop(); 0101 QCOMPARE(m_result, int(KIO::ERR_CANNOT_OPEN_FOR_READING)); 0102 } 0103 0104 void ImageJobTest::testUnreadable() { 0105 QTemporaryFile tmpFile; 0106 QVERIFY(tmpFile.open()); 0107 QVERIFY(tmpFile.setPermissions(QFileDevice::Permissions())); 0108 QUrl u = QUrl::fromLocalFile(tmpFile.fileName()); 0109 0110 Tellico::ImageJob* job = new Tellico::ImageJob(u); 0111 connect(job, &KJob::result, 0112 this, &ImageJobTest::slotGetResult); 0113 0114 enterLoop(); 0115 QCOMPARE(m_result, int(KIO::ERR_CANNOT_OPEN_FOR_READING)); 0116 0117 const Tellico::Data::Image& img = job->image(); 0118 QVERIFY(img.isNull()); 0119 } 0120 0121 void ImageJobTest::testImageInvalid() { 0122 // text file is an invalid image 0123 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("imagejobtest.cpp")); 0124 0125 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0126 connect(job.data(), &KJob::result, 0127 this, &ImageJobTest::slotGetResult); 0128 0129 enterLoop(); 0130 QCOMPARE(m_result, int(KIO::ERR_UNKNOWN)); 0131 0132 const Tellico::Data::Image& img = job->image(); 0133 QVERIFY(img.isNull()); 0134 QCOMPARE(img.linkOnly(), false); 0135 } 0136 0137 void ImageJobTest::testImageLoad() { 0138 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0139 0140 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0141 connect(job.data(), &KJob::result, 0142 this, &ImageJobTest::slotGetResult); 0143 0144 enterLoop(); 0145 // success! 0146 QCOMPARE(m_result, 0); 0147 0148 const Tellico::Data::Image& img = job->image(); 0149 QVERIFY(!img.isNull()); 0150 QCOMPARE(img.id(), QStringLiteral("dde5bf2cbd90fad8635a26dfb362e0ff.png")); 0151 QCOMPARE(img.format(), QByteArray("png")); 0152 QCOMPARE(img.linkOnly(), false); 0153 0154 // check that the job is automatically deleted 0155 qApp->processEvents(); 0156 QVERIFY(!job); 0157 } 0158 0159 void ImageJobTest::testImageLoadWithId() { 0160 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0161 0162 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u, QStringLiteral("tellico-rocks")); 0163 connect(job.data(), &KJob::result, 0164 this, &ImageJobTest::slotGetResult); 0165 0166 enterLoop(); 0167 // success! 0168 QCOMPARE(m_result, 0); 0169 0170 const Tellico::Data::Image& img = job->image(); 0171 QVERIFY(!img.isNull()); 0172 QCOMPARE(img.id(), QStringLiteral("tellico-rocks")); 0173 QCOMPARE(img.format(), QByteArray("png")); 0174 QCOMPARE(img.linkOnly(), false); 0175 } 0176 0177 void ImageJobTest::testImageLink() { 0178 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0179 0180 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u, 0181 QString() /* id */, 0182 false /* quiet */); 0183 job->setLinkOnly(true); 0184 connect(job.data(), &KJob::result, 0185 this, &ImageJobTest::slotGetResult); 0186 0187 enterLoop(); 0188 // success! 0189 QCOMPARE(m_result, 0); 0190 0191 const Tellico::Data::Image& img = job->image(); 0192 QVERIFY(!img.isNull()); 0193 // id is not the MD5 hash 0194 QVERIFY(img.id() != QStringLiteral("dde5bf2cbd90fad8635a26dfb362e0ff.png")); 0195 QCOMPARE(img.format(), QByteArray("png")); 0196 QCOMPARE(img.linkOnly(), true); 0197 } 0198 0199 void ImageJobTest::testNetworkImage() { 0200 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0201 0202 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0203 0204 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0205 connect(job.data(), &KJob::result, 0206 this, &ImageJobTest::slotGetResult); 0207 0208 enterLoop(); 0209 // success! 0210 QCOMPARE(m_result, 0); 0211 0212 const Tellico::Data::Image& img = job->image(); 0213 QVERIFY(!img.isNull()); 0214 QCOMPARE(img.id(), QStringLiteral("ecaf5185c4016881aaabb4933211d5d6.png")); 0215 QCOMPARE(img.format(), QByteArray("png")); 0216 QCOMPARE(img.linkOnly(), false); 0217 0218 // check that the job is automatically deleted 0219 qApp->processEvents(); 0220 QVERIFY(!job); 0221 } 0222 0223 void ImageJobTest::testNetworkImageLink() { 0224 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0225 0226 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0227 0228 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u, 0229 QString() /* id */, 0230 false /* quiet */); 0231 job->setLinkOnly(true); 0232 connect(job.data(), &KJob::result, 0233 this, &ImageJobTest::slotGetResult); 0234 0235 enterLoop(); 0236 // success! 0237 QCOMPARE(m_result, 0); 0238 0239 const Tellico::Data::Image& img = job->image(); 0240 QVERIFY(!img.isNull()); 0241 QCOMPARE(img.id(), u.url()); 0242 QCOMPARE(img.format(), QByteArray("png")); 0243 QCOMPARE(img.linkOnly(), true); 0244 } 0245 0246 void ImageJobTest::testNetworkImageInvalid() { 0247 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0248 0249 QUrl u(QStringLiteral("https://tellico-project.org")); 0250 0251 QPointer<Tellico::ImageJob> job = new Tellico::ImageJob(u); 0252 connect(job.data(), &KJob::result, 0253 this, &ImageJobTest::slotGetResult); 0254 0255 enterLoop(); 0256 QCOMPARE(m_result, int(KIO::ERR_UNKNOWN)); 0257 0258 const Tellico::Data::Image& img = job->image(); 0259 QVERIFY(img.isNull()); 0260 } 0261 0262 void ImageJobTest::testFactoryRequestLocal() { 0263 QVERIFY(m_imageId.isEmpty()); 0264 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0265 this, &ImageJobTest::slotAvailable); 0266 0267 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/tellico.png")); 0268 Tellico::ImageFactory::requestImageById(u.url()); 0269 0270 // don't need to enter loop since the image is local and signal fires immediately 0271 QVERIFY(!m_imageId.isEmpty()); 0272 // success! 0273 QCOMPARE(m_result, 0); 0274 0275 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0276 QVERIFY(!img.isNull()); 0277 // id is not the MD5 hash 0278 QVERIFY(img.id() != QStringLiteral("dde5bf2cbd90fad8635a26dfb362e0ff.png")); 0279 QCOMPARE(img.format(), QByteArray("png")); 0280 QCOMPARE(img.linkOnly(), true); 0281 } 0282 0283 void ImageJobTest::testFactoryRequestLocalInvalid() { 0284 QVERIFY(m_imageId.isEmpty()); 0285 QSignalSpy spy(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable); 0286 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0287 this, &ImageJobTest::slotAvailable); 0288 0289 // text file is an invalid image 0290 QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("imagejobtest.cpp")); 0291 Tellico::ImageFactory::requestImageById(u.url()); 0292 0293 // it will be a null image, but a local url, so image is still loaded with immediate signal 0294 QCOMPARE(spy.count(), 1); 0295 // the available image id is the url 0296 QCOMPARE(m_imageId, u.url()); 0297 0298 // now try to load it 0299 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0300 QVERIFY(img.isNull()); 0301 QCOMPARE(img.linkOnly(), false); 0302 // make sure the null image list is updated 0303 QVERIFY(Tellico::ImageFactory::self()->hasNullImage(m_imageId)); 0304 // the image should not be in local memory now 0305 QVERIFY(!Tellico::ImageFactory::self()->hasImageInMemory(m_imageId)); 0306 QVERIFY(!Tellico::ImageFactory::self()->hasImageInfo(m_imageId)); 0307 } 0308 0309 void ImageJobTest::testFactoryRequestNetwork() { 0310 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0311 0312 QVERIFY(m_imageId.isEmpty()); 0313 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0314 this, &ImageJobTest::slotAvailable); 0315 0316 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0317 Tellico::ImageFactory::requestImageById(u.url()); 0318 0319 enterLoop(); 0320 QVERIFY(!m_imageId.isEmpty()); 0321 // success! 0322 QCOMPARE(m_result, 0); 0323 // the image should be in local memory now 0324 QVERIFY(Tellico::ImageFactory::self()->hasImageInMemory(m_imageId)); 0325 QVERIFY(Tellico::ImageFactory::self()->hasImageInfo(m_imageId)); 0326 0327 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0328 QVERIFY(!img.isNull()); 0329 // id is the MD5 hash, since it's not link only 0330 QCOMPARE(img.id(), QStringLiteral("ecaf5185c4016881aaabb4933211d5d6.png")); 0331 QCOMPARE(img.format(), QByteArray("png")); 0332 QCOMPARE(img.linkOnly(), false); 0333 } 0334 0335 void ImageJobTest::testFactoryRequestNetworkLinkOnly() { 0336 if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle); 0337 0338 QVERIFY(m_imageId.isEmpty()); 0339 connect(Tellico::ImageFactory::self(), &Tellico::ImageFactory::imageAvailable, 0340 this, &ImageJobTest::slotAvailable); 0341 0342 QUrl u(QStringLiteral("https://tellico-project.org/wp-content/uploads/96-tellico.png")); 0343 // first, tell the image factory that the image is link only 0344 Tellico::Data::ImageInfo info(u.url(), "PNG", 64, 64, true /* link only */); 0345 Tellico::ImageFactory::cacheImageInfo(info); 0346 0347 Tellico::ImageFactory::requestImageById(u.url()); 0348 0349 enterLoop(); 0350 QVERIFY(!m_imageId.isEmpty()); 0351 // success! 0352 QCOMPARE(m_result, 0); 0353 // the image should be in local memory now 0354 QVERIFY(Tellico::ImageFactory::self()->hasImageInMemory(m_imageId)); 0355 QVERIFY(Tellico::ImageFactory::self()->hasImageInfo(m_imageId)); 0356 0357 const Tellico::Data::Image& img = Tellico::ImageFactory::imageById(m_imageId); 0358 QVERIFY(!img.isNull()); 0359 // id is not the MD5 hash 0360 QCOMPARE(img.id(), u.url()); 0361 QCOMPARE(img.format(), QByteArray("png")); 0362 QCOMPARE(img.linkOnly(), true); 0363 }