on master help sign in
216 lines 6.4 kB history raw
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include <QCoreApplication>
18#include <QFileInfo>
19#include <QImageReader>
20#include <QQuickView>
21#include <QTemporaryDir>
22#include <QtTestGui>
23#include <private/qquickimage_p.h>
24#include <time.h>
25#include <utime.h>
27#include <paths.h>
29Q_DECLARE_METATYPE(QQuickImage::Status)
31class ImageCacheTest : public QObject
33 Q_OBJECT
35private:
37 void setUpImage(const QString &name, const QSize &sourceSize = QSize())
38 {
39 QString url = "image://unity8imagecache/file://" + sourceFile(name);
40 image->setProperty("sourceSize", sourceSize);
41 image->setProperty("source", url);
42 }
44 void waitForImage(QQuickImage::Status status = QQuickImage::Ready)
45 {
46 QTRY_COMPARE(image->property("status"), QVariant((int)status));
47 }
49 QSize cachedImageSize(const QString &filename)
50 {
51 QImageReader reader(filename);
52 return reader.size();
53 }
55 QString sourceFile(const QString &name)
56 {
57 return testDataDir() + "/" TEST_DIR "/graphics/" + name;
58 }
60 QString cachedFile(bool isPath, const QString &name)
61 {
62 if (isPath)
63 return home->path() + "/.cache/unity8/imagecache/paths" + sourceFile(name);
64 else
65 return home->path() + "/.cache/unity8/imagecache/names/" + name;
66 }
68 void createCachedImage(const QString &name, const QString &cachePath, const QSize &cacheSize, time_t mtime_in = 0)
69 {
70 QString origPath = sourceFile(name);
71 QImageReader origImage(origPath);
72 origImage.setScaledSize(cacheSize);
73 auto format = origImage.format(); // can't get this after reading
75 QImage cacheImage(origImage.read());
76 QVERIFY(!cacheImage.isNull());
78 QFileInfo(cachePath).dir().mkpath(QStringLiteral("."));
79 QVERIFY(cacheImage.save(cachePath, format, 100));
81 // Make file a few seconds old, so we can more easily tell if it gets updated
82 auto mtime = mtime_in == 0 ? QFileInfo(cachePath).lastModified().toTime_t() - 5 : mtime_in;
83 struct utimbuf timebuffer;
84 timebuffer.modtime = mtime;
85 timebuffer.actime = timebuffer.modtime;
86 QCOMPARE(utime(cachePath.toUtf8().data(), &timebuffer), 0);
87 }
89private Q_SLOTS:
91 void init()
92 {
93 home = new QTemporaryDir();
94 QVERIFY(home->isValid());
95 qputenv("HOME", home->path().toUtf8());
97 view = new QQuickView();
98 view->setSource(QUrl::fromLocalFile(testDataDir() + "/" TEST_DIR "/test.qml"));
99 image = view->rootObject();
101 view->show();
102 QTest::qWaitForWindowExposed(view);
104 waitForImage(QQuickImage::Null);
105 }
107 void cleanup()
108 {
109 delete view;
110 delete home;
111 }
113 void testFileNotFound()
114 {
115 setUpImage("NOTHERE");
116 waitForImage(QQuickImage::Error);
117 QVERIFY(!QFile::exists(cachedFile(true, "NOTHERE")));
118 }
120 void testNoSourceSize()
121 {
122 setUpImage("wide.jpg");
123 waitForImage();
124 QVERIFY(!QFile::exists(cachedFile(true, "wide.jpg")));
125 }
127 void testNoScalingUp()
128 {
129 setUpImage("wide.jpg", QSize(1000, 1000));
130 waitForImage();
131 QVERIFY(!QFile::exists(cachedFile(true, "wide.jpg")));
132 }
134 void testFullSourceSize()
135 {
136 setUpImage("wide.jpg", QSize(100, 100));
137 waitForImage();
138 QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(100, 100));
139 }
141 void testWidthSourceSize()
142 {
143 setUpImage("wide.jpg", QSize(100, 0));
144 waitForImage();
145 // wide.jpg is 500x200
146 QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(100, 40));
147 }
149 void testHeightSourceSize()
150 {
151 setUpImage("wide.jpg", QSize(0, 100));
152 waitForImage();
153 // wide.jpg is 500x200
154 QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(250, 100));
155 }
157 void testNameArg()
158 {
159 setUpImage("wide.jpg?name=foo", QSize(0, 100));
160 waitForImage();
161 QVERIFY(!QFile::exists(cachedFile(true, ""))); // check for dir itself
162 QVERIFY(QFile::exists(cachedFile(false, "foo")));
163 }
165 void testLoadCache()
166 {
167 auto cacheName = cachedFile(false, "foo");
168 createCachedImage("wide.jpg", cacheName, QSize(250, 100));
169 auto mtime = QFileInfo(cacheName).lastModified();
171 auto now = time(NULL);
172 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
174 setUpImage("wide.jpg?name=foo", QSize(0, 100));
175 waitForImage();
176 QCOMPARE(QFileInfo(cacheName).lastModified(), mtime); // wasn't recreated
177 }
179 void testDifferentSize()
180 {
181 auto cacheName = cachedFile(false, "foo");
182 createCachedImage("wide.jpg", cacheName, QSize(250, 100));
184 auto now = time(NULL);
185 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
187 setUpImage("wide.jpg?name=foo", QSize(100, 0));
188 waitForImage();
189 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() >= now); // was recreated
190 }
192 void testStaleCache()
193 {
194 auto sourceName = sourceFile("wide.jpg");
195 auto mtime = QFileInfo(sourceName).lastModified().toTime_t() - 5;
197 auto cacheName = cachedFile(false, "foo");
198 createCachedImage("wide.jpg", cacheName, QSize(250, 100), mtime);
200 auto now = time(NULL);
201 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
203 setUpImage("wide.jpg?name=foo", QSize(0, 100));
204 waitForImage();
205 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() >= now); // was recreated
206 }
208private:
209 QQuickView *view;
210 QObject *image;
211 QTemporaryDir *home;
212};
214QTEST_MAIN(ImageCacheTest)
216#include "test.moc"