1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <private/qdeclarativepixmapcache_p.h>
44 #include <QtDeclarative/qdeclarativeengine.h>
45 #include <QtDeclarative/qdeclarativeimageprovider.h>
46 #include <QNetworkReply>
47 #include "testhttpserver.h"
48 #include "../../../shared/util.h"
50 #ifndef QT_NO_CONCURRENT
51 #include <qtconcurrentrun.h>
55 // These don't let normal people run tests!
56 //#include "../network-settings.h"
59 // In Symbian OS test data is located in applications private dir
63 class tst_qdeclarativepixmapcache : public QObject
67 tst_qdeclarativepixmapcache() :
68 thisfile(QUrl::fromLocalFile(__FILE__)),
71 server.serveDirectory(SRCDIR "/data/http");
82 #ifndef QT_NO_CONCURRENT
86 QDeclarativeEngine engine;
88 TestHTTPServer server;
92 static int slotters=0;
94 class Slotter : public QObject
111 QTestEventLoop::instance().exitLoop();
115 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
116 static const bool localfile_optimized = true;
118 static const bool localfile_optimized = false;
121 void tst_qdeclarativepixmapcache::single_data()
123 // Note, since QDeclarativePixmapCache is shared, tests affect each other!
124 // so use different files fore all test functions.
126 QTest::addColumn<QUrl>("target");
127 QTest::addColumn<bool>("incache");
128 QTest::addColumn<bool>("exists");
129 QTest::addColumn<bool>("neterror");
131 // File URLs are optimized
132 QTest::newRow("local") << thisfile.resolved(QUrl("data/exists.png")) << localfile_optimized << true << false;
133 QTest::newRow("local") << thisfile.resolved(QUrl("data/notexists.png")) << localfile_optimized << false << false;
134 QTest::newRow("remote") << QUrl("http://127.0.0.1:14452/exists.png") << false << true << false;
135 QTest::newRow("remote") << QUrl("http://127.0.0.1:14452/notexists.png") << false << false << true;
138 void tst_qdeclarativepixmapcache::single()
140 QFETCH(QUrl, target);
141 QFETCH(bool, incache);
142 QFETCH(bool, exists);
143 QFETCH(bool, neterror);
145 QString expectedError;
147 expectedError = "Error downloading " + target.toString() + " - server replied: Not found";
148 } else if (!exists) {
149 expectedError = "Cannot open: " + target.toString();
152 QDeclarativePixmap pixmap;
153 QVERIFY(pixmap.width() <= 0); // Check Qt assumption
155 pixmap.load(&engine, target);
158 QCOMPARE(pixmap.error(), expectedError);
160 QVERIFY(pixmap.status() == QDeclarativePixmap::Ready);
161 QVERIFY(pixmap.width() > 0);
163 QVERIFY(pixmap.status() == QDeclarativePixmap::Error);
164 QVERIFY(pixmap.width() <= 0);
167 QVERIFY(pixmap.width() <= 0);
170 pixmap.connectFinished(&getter, SLOT(got()));
171 QTestEventLoop::instance().enterLoop(10);
172 QVERIFY(!QTestEventLoop::instance().timeout());
173 QVERIFY(getter.gotslot);
175 QVERIFY(pixmap.status() == QDeclarativePixmap::Ready);
176 QVERIFY(pixmap.width() > 0);
178 QVERIFY(pixmap.status() == QDeclarativePixmap::Error);
179 QVERIFY(pixmap.width() <= 0);
181 QCOMPARE(pixmap.error(), expectedError);
185 void tst_qdeclarativepixmapcache::parallel_data()
187 // Note, since QDeclarativePixmapCache is shared, tests affect each other!
188 // so use different files fore all test functions.
190 QTest::addColumn<QUrl>("target1");
191 QTest::addColumn<QUrl>("target2");
192 QTest::addColumn<int>("incache");
193 QTest::addColumn<int>("cancel"); // which one to cancel
195 QTest::newRow("local")
196 << thisfile.resolved(QUrl("data/exists1.png"))
197 << thisfile.resolved(QUrl("data/exists2.png"))
198 << (localfile_optimized ? 2 : 0)
201 QTest::newRow("remote")
202 << QUrl("http://127.0.0.1:14452/exists2.png")
203 << QUrl("http://127.0.0.1:14452/exists3.png")
207 QTest::newRow("remoteagain")
208 << QUrl("http://127.0.0.1:14452/exists2.png")
209 << QUrl("http://127.0.0.1:14452/exists3.png")
213 QTest::newRow("remotecopy")
214 << QUrl("http://127.0.0.1:14452/exists4.png")
215 << QUrl("http://127.0.0.1:14452/exists4.png")
219 QTest::newRow("remotecopycancel")
220 << QUrl("http://127.0.0.1:14452/exists5.png")
221 << QUrl("http://127.0.0.1:14452/exists5.png")
226 void tst_qdeclarativepixmapcache::parallel()
228 QFETCH(QUrl, target1);
229 QFETCH(QUrl, target2);
230 QFETCH(int, incache);
234 targets << target1 << target2;
236 QList<QDeclarativePixmap *> pixmaps;
238 QList<Slotter*> getters;
240 for (int i=0; i<targets.count(); ++i) {
241 QUrl target = targets.at(i);
242 QDeclarativePixmap *pixmap = new QDeclarativePixmap;
244 pixmap->load(&engine, target);
246 QVERIFY(pixmap->status() != QDeclarativePixmap::Error);
247 pixmaps.append(pixmap);
248 if (pixmap->isReady()) {
249 QVERIFY(pixmap->width() > 0);
251 pending.append(false);
253 QVERIFY(pixmap->width() <= 0);
254 getters.append(new Slotter);
255 pixmap->connectFinished(getters[i], SLOT(got()));
256 pending.append(true);
260 QCOMPARE(incache+slotters, targets.count());
263 pixmaps.at(cancel)->clear(getters[cancel]);
268 QTestEventLoop::instance().enterLoop(10);
269 QVERIFY(!QTestEventLoop::instance().timeout());
272 for (int i=0; i<targets.count(); ++i) {
273 QDeclarativePixmap *pixmap = pixmaps[i];
276 QVERIFY(!getters[i]->gotslot);
279 QVERIFY(getters[i]->gotslot);
281 QVERIFY(pixmap->isReady());
282 QVERIFY(pixmap->width() > 0);
290 void tst_qdeclarativepixmapcache::massive()
292 QDeclarativeEngine engine;
293 QUrl url = thisfile.resolved(QUrl("data/massive.png"));
295 // Confirm that massive images remain in the cache while they are
296 // in use by the application.
299 QDeclarativePixmap p(&engine, url);
300 QVERIFY(p.isReady());
301 QVERIFY(p.pixmap().size() == QSize(10000, 1000));
302 cachekey = p.pixmap().cacheKey();
304 QDeclarativePixmap p2(&engine, url);
305 QVERIFY(p2.isReady());
306 QVERIFY(p2.pixmap().size() == QSize(10000, 1000));
308 QVERIFY(p2.pixmap().cacheKey() == cachekey);
311 // Confirm that massive images are removed from the cache when
312 // they become unused
316 QDeclarativePixmap p(&engine, url);
317 QVERIFY(p.isReady());
318 QVERIFY(p.pixmap().size() == QSize(10000, 1000));
319 cachekey = p.pixmap().cacheKey();
322 QDeclarativePixmap p2(&engine, url);
323 QVERIFY(p2.isReady());
324 QVERIFY(p2.pixmap().size() == QSize(10000, 1000));
326 QVERIFY(p2.pixmap().cacheKey() != cachekey);
331 void tst_qdeclarativepixmapcache::cancelcrash()
333 QUrl url("http://127.0.0.1:14452/cancelcrash_notexist.png");
334 for (int ii = 0; ii < 1000; ++ii) {
335 QDeclarativePixmap pix(&engine, url);
339 class MyPixmapProvider : public QDeclarativeImageProvider
343 : QDeclarativeImageProvider(Pixmap) {}
345 virtual QPixmap requestPixmap(const QString &d, QSize *, const QSize &) {
347 QPixmap pix(800, 600);
354 void tst_qdeclarativepixmapcache::shrinkcache()
356 QDeclarativeEngine engine;
357 engine.addImageProvider(QLatin1String("mypixmaps"), new MyPixmapProvider);
359 for (int ii = 0; ii < 4000; ++ii) {
360 QUrl url("image://mypixmaps/" + QString::number(ii));
361 QDeclarativePixmap p(&engine, url);
365 #ifndef QT_NO_CONCURRENT
367 void createNetworkServer()
369 QEventLoop eventLoop;
370 TestHTTPServer server(14453);
371 server.serveDirectory(SRCDIR "/data/http");
372 QTimer::singleShot(100, &eventLoop, SLOT(quit()));
376 #ifndef QT_NO_CONCURRENT
378 void tst_qdeclarativepixmapcache::networkCrash()
380 QFuture<void> future = QtConcurrent::run(createNetworkServer);
381 QDeclarativeEngine engine;
382 for (int ii = 0; ii < 100 ; ++ii) {
383 QDeclarativePixmap* pixmap = new QDeclarativePixmap;
384 pixmap->load(&engine, QUrl(QString("http://127.0.0.1:14453/exists.png")));
395 QTEST_MAIN(tst_qdeclarativepixmapcache)
397 #include "tst_qdeclarativepixmapcache.moc"