on vivid help sign in
214 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>
27Q_DECLARE_METATYPE(QQuickImage::Status)
29class ImageCacheTest : public QObject
31 Q_OBJECT
33private:
35 void setUpImage(const QString &name, const QSize &sourceSize = QSize())
36 {
37 QString url = "image://unity8imagecache/file://" + sourceFile(name);
38 image->setProperty("sourceSize", sourceSize);
39 image->setProperty("source", url);
40 }
42 void waitForImage(QQuickImage::Status status = QQuickImage::Ready)
43 {
44 QTRY_COMPARE(image->property("status"), QVariant((int)status));
45 }
47 QSize cachedImageSize(const QString &filename)
48 {
49 QImageReader reader(filename);
50 return reader.size();
51 }
53 QString sourceFile(const QString &name)
54 {
55 return CURRENT_SOURCE_DIR "/graphics/" + name;
56 }
58 QString cachedFile(bool isPath, const QString &name)
59 {
60 if (isPath)
61 return home->path() + "/.cache/unity8/imagecache/paths" + sourceFile(name);
62 else
63 return home->path() + "/.cache/unity8/imagecache/names/" + name;
64 }
66 void createCachedImage(const QString &name, const QString &cachePath, const QSize &cacheSize, time_t mtime_in = 0)
67 {
68 QString origPath = sourceFile(name);
69 QImageReader origImage(origPath);
70 origImage.setScaledSize(cacheSize);
71 auto format = origImage.format(); // can't get this after reading
73 QImage cacheImage(origImage.read());
74 QVERIFY(!cacheImage.isNull());
76 QFileInfo(cachePath).dir().mkpath(QStringLiteral("."));
77 QVERIFY(cacheImage.save(cachePath, format, 100));
79 // Make file a few seconds old, so we can more easily tell if it gets updated
80 auto mtime = mtime_in == 0 ? QFileInfo(cachePath).lastModified().toTime_t() - 5 : mtime_in;
81 struct utimbuf timebuffer;
82 timebuffer.modtime = mtime;
83 timebuffer.actime = timebuffer.modtime;
84 QCOMPARE(utime(cachePath.toUtf8().data(), &timebuffer), 0);
85 }
87private Q_SLOTS:
89 void init()
90 {
91 home = new QTemporaryDir();
92 QVERIFY(home->isValid());
93 qputenv("HOME", home->path().toUtf8());
95 view = new QQuickView();
96 view->setSource(QUrl::fromLocalFile(CURRENT_SOURCE_DIR "/test.qml"));
97 image = view->rootObject();
99 view->show();
100 QTest::qWaitForWindowExposed(view);
102 waitForImage(QQuickImage::Null);
103 }
105 void cleanup()
106 {
107 delete view;
108 delete home;
109 }
111 void testFileNotFound()
112 {
113 setUpImage("NOTHERE");
114 waitForImage(QQuickImage::Error);
115 QVERIFY(!QFile::exists(cachedFile(true, "NOTHERE")));
116 }
118 void testNoSourceSize()
119 {
120 setUpImage("wide.jpg");
121 waitForImage();
122 QVERIFY(!QFile::exists(cachedFile(true, "wide.jpg")));
123 }
125 void testNoScalingUp()
126 {
127 setUpImage("wide.jpg", QSize(1000, 1000));
128 waitForImage();
129 QVERIFY(!QFile::exists(cachedFile(true, "wide.jpg")));
130 }
132 void testFullSourceSize()
133 {
134 setUpImage("wide.jpg", QSize(100, 100));
135 waitForImage();
136 QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(100, 100));
137 }
139 void testWidthSourceSize()
140 {
141 setUpImage("wide.jpg", QSize(100, 0));
142 waitForImage();
143 // wide.jpg is 500x200
144 QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(100, 40));
145 }
147 void testHeightSourceSize()
148 {
149 setUpImage("wide.jpg", QSize(0, 100));
150 waitForImage();
151 // wide.jpg is 500x200
152 QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(250, 100));
153 }
155 void testNameArg()
156 {
157 setUpImage("wide.jpg?name=foo", QSize(0, 100));
158 waitForImage();
159 QVERIFY(!QFile::exists(cachedFile(true, ""))); // check for dir itself
160 QVERIFY(QFile::exists(cachedFile(false, "foo")));
161 }
163 void testLoadCache()
164 {
165 auto cacheName = cachedFile(false, "foo");
166 createCachedImage("wide.jpg", cacheName, QSize(250, 100));
167 auto mtime = QFileInfo(cacheName).lastModified();
169 auto now = time(NULL);
170 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
172 setUpImage("wide.jpg?name=foo", QSize(0, 100));
173 waitForImage();
174 QCOMPARE(QFileInfo(cacheName).lastModified(), mtime); // wasn't recreated
175 }
177 void testDifferentSize()
178 {
179 auto cacheName = cachedFile(false, "foo");
180 createCachedImage("wide.jpg", cacheName, QSize(250, 100));
182 auto now = time(NULL);
183 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
185 setUpImage("wide.jpg?name=foo", QSize(100, 0));
186 waitForImage();
187 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() >= now); // was recreated
188 }
190 void testStaleCache()
191 {
192 auto sourceName = sourceFile("wide.jpg");
193 auto mtime = QFileInfo(sourceName).lastModified().toTime_t() - 5;
195 auto cacheName = cachedFile(false, "foo");
196 createCachedImage("wide.jpg", cacheName, QSize(250, 100), mtime);
198 auto now = time(NULL);
199 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
201 setUpImage("wide.jpg?name=foo", QSize(0, 100));
202 waitForImage();
203 QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() >= now); // was recreated
204 }
206private:
207 QQuickView *view;
208 QObject *image;
209 QTemporaryDir *home;
210};
212QTEST_MAIN(ImageCacheTest)
214#include "test.moc"