|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 |
|
43 #include <QtTest/QtTest> |
|
44 |
|
45 |
|
46 #include <qpixmapcache.h> |
|
47 #include "../../../src/gui/image/qpixmapcache_p.h" |
|
48 |
|
49 |
|
50 //TESTED_CLASS= |
|
51 //TESTED_FILES= |
|
52 |
|
53 class tst_QPixmapCache : public QObject |
|
54 { |
|
55 Q_OBJECT |
|
56 |
|
57 public: |
|
58 tst_QPixmapCache(); |
|
59 virtual ~tst_QPixmapCache(); |
|
60 |
|
61 |
|
62 public slots: |
|
63 void init(); |
|
64 private slots: |
|
65 void cacheLimit(); |
|
66 void setCacheLimit(); |
|
67 void find(); |
|
68 void insert(); |
|
69 void replace(); |
|
70 void remove(); |
|
71 void clear(); |
|
72 void pixmapKey(); |
|
73 }; |
|
74 |
|
75 static QPixmapCache::KeyData* getPrivate(QPixmapCache::Key &key) |
|
76 { |
|
77 return (*reinterpret_cast<QPixmapCache::KeyData**>(&key)); |
|
78 } |
|
79 |
|
80 static QPixmapCache::KeyData** getPrivateRef(QPixmapCache::Key &key) |
|
81 { |
|
82 return (reinterpret_cast<QPixmapCache::KeyData**>(&key)); |
|
83 } |
|
84 |
|
85 static int originalCacheLimit; |
|
86 |
|
87 tst_QPixmapCache::tst_QPixmapCache() |
|
88 { |
|
89 originalCacheLimit = QPixmapCache::cacheLimit(); |
|
90 } |
|
91 |
|
92 tst_QPixmapCache::~tst_QPixmapCache() |
|
93 { |
|
94 } |
|
95 |
|
96 void tst_QPixmapCache::init() |
|
97 { |
|
98 QPixmapCache::setCacheLimit(originalCacheLimit); |
|
99 QPixmapCache::clear(); |
|
100 } |
|
101 |
|
102 void tst_QPixmapCache::cacheLimit() |
|
103 { |
|
104 // make sure the default is reasonable; |
|
105 // it was between 2048 and 10240 last time I looked at it |
|
106 QVERIFY(originalCacheLimit >= 1024 && originalCacheLimit <= 20480); |
|
107 |
|
108 QPixmapCache::setCacheLimit(100); |
|
109 QCOMPARE(QPixmapCache::cacheLimit(), 100); |
|
110 |
|
111 QPixmapCache::setCacheLimit(-50); |
|
112 QCOMPARE(QPixmapCache::cacheLimit(), -50); |
|
113 } |
|
114 |
|
115 void tst_QPixmapCache::setCacheLimit() |
|
116 { |
|
117 QPixmap *p1 = new QPixmap(2, 3); |
|
118 QPixmapCache::insert("P1", *p1); |
|
119 QVERIFY(QPixmapCache::find("P1") != 0); |
|
120 delete p1; |
|
121 |
|
122 QPixmapCache::setCacheLimit(0); |
|
123 QVERIFY(QPixmapCache::find("P1") == 0); |
|
124 |
|
125 p1 = new QPixmap(2, 3); |
|
126 QPixmapCache::setCacheLimit(1000); |
|
127 QPixmapCache::insert("P1", *p1); |
|
128 QVERIFY(QPixmapCache::find("P1") != 0); |
|
129 |
|
130 delete p1; |
|
131 |
|
132 //The int part of the API |
|
133 p1 = new QPixmap(2, 3); |
|
134 QPixmapCache::Key key = QPixmapCache::insert(*p1); |
|
135 QVERIFY(QPixmapCache::find(key, p1) != 0); |
|
136 delete p1; |
|
137 |
|
138 QPixmapCache::setCacheLimit(0); |
|
139 QVERIFY(QPixmapCache::find(key, p1) == 0); |
|
140 |
|
141 p1 = new QPixmap(2, 3); |
|
142 QPixmapCache::setCacheLimit(1000); |
|
143 QPixmapCache::replace(key, *p1); |
|
144 QVERIFY(QPixmapCache::find(key, p1) == 0); |
|
145 |
|
146 delete p1; |
|
147 |
|
148 //Let check if keys are released when the pixmap cache is |
|
149 //full or has been flushed. |
|
150 QPixmapCache::clear(); |
|
151 p1 = new QPixmap(2, 3); |
|
152 key = QPixmapCache::insert(*p1); |
|
153 QVERIFY(QPixmapCache::find(key, p1) != 0); |
|
154 QPixmapCache::setCacheLimit(0); |
|
155 QVERIFY(QPixmapCache::find(key, p1) == 0); |
|
156 QPixmapCache::setCacheLimit(1000); |
|
157 key = QPixmapCache::insert(*p1); |
|
158 QCOMPARE(getPrivate(key)->isValid, true); |
|
159 QCOMPARE(getPrivate(key)->key, 1); |
|
160 |
|
161 delete p1; |
|
162 |
|
163 //Let check if removing old entries doesn't let you get |
|
164 // wrong pixmaps |
|
165 QPixmapCache::clear(); |
|
166 QPixmap p2; |
|
167 p1 = new QPixmap(2, 3); |
|
168 key = QPixmapCache::insert(*p1); |
|
169 QVERIFY(QPixmapCache::find(key, &p2) != 0); |
|
170 //we flush the cache |
|
171 QPixmapCache::setCacheLimit(0); |
|
172 QPixmapCache::setCacheLimit(1000); |
|
173 QPixmapCache::Key key2 = QPixmapCache::insert(*p1); |
|
174 QCOMPARE(getPrivate(key2)->key, 1); |
|
175 QVERIFY(QPixmapCache::find(key, &p2) == 0); |
|
176 QVERIFY(QPixmapCache::find(key2, &p2) != 0); |
|
177 QCOMPARE(p2, *p1); |
|
178 |
|
179 delete p1; |
|
180 |
|
181 //Here we simulate the flushing when the app is idle |
|
182 /*QPixmapCache::clear(); |
|
183 QPixmapCache::setCacheLimit(originalCacheLimit); |
|
184 p1 = new QPixmap(300, 300); |
|
185 key = QPixmapCache::insert(*p1); |
|
186 QCOMPARE(getPrivate(key)->key, 1); |
|
187 key2 = QPixmapCache::insert(*p1); |
|
188 key2 = QPixmapCache::insert(*p1); |
|
189 QPixmapCache::Key key3 = QPixmapCache::insert(*p1); |
|
190 QTest::qWait(32000); |
|
191 key2 = QPixmapCache::insert(*p1); |
|
192 QCOMPARE(getPrivate(key2)->key, 1); |
|
193 //This old key is not valid anymore after the flush |
|
194 QCOMPARE(getPrivate(key)->isValid, false); |
|
195 QVERIFY(QPixmapCache::find(key, &p2) == 0); |
|
196 delete p1;*/ |
|
197 } |
|
198 |
|
199 void tst_QPixmapCache::find() |
|
200 { |
|
201 QPixmap p1(10, 10); |
|
202 p1.fill(Qt::red); |
|
203 QVERIFY(QPixmapCache::insert("P1", p1)); |
|
204 |
|
205 QPixmap p2; |
|
206 QVERIFY(QPixmapCache::find("P1", p2)); |
|
207 QCOMPARE(p2.width(), 10); |
|
208 QCOMPARE(p2.height(), 10); |
|
209 QCOMPARE(p1, p2); |
|
210 |
|
211 // obsolete |
|
212 QPixmap *p3 = QPixmapCache::find("P1"); |
|
213 QVERIFY(p3); |
|
214 QCOMPARE(p1, *p3); |
|
215 |
|
216 //The int part of the API |
|
217 QPixmapCache::Key key = QPixmapCache::insert(p1); |
|
218 |
|
219 QVERIFY(QPixmapCache::find(key, &p2)); |
|
220 QCOMPARE(p2.width(), 10); |
|
221 QCOMPARE(p2.height(), 10); |
|
222 QCOMPARE(p1, p2); |
|
223 |
|
224 QPixmapCache::clear(); |
|
225 QPixmapCache::setCacheLimit(128); |
|
226 |
|
227 key = QPixmapCache::insert(p1); |
|
228 |
|
229 //The int part of the API |
|
230 QList<QPixmapCache::Key> keys; |
|
231 for (int i = 0; i < 4000; ++i) |
|
232 QPixmapCache::insert(p1); |
|
233 |
|
234 //at that time the first key has been erase because no more place in the cache |
|
235 QVERIFY(QPixmapCache::find(key, &p1) == 0); |
|
236 QCOMPARE(getPrivate(key)->isValid, false); |
|
237 } |
|
238 |
|
239 void tst_QPixmapCache::insert() |
|
240 { |
|
241 QPixmap p1(10, 10); |
|
242 p1.fill(Qt::red); |
|
243 |
|
244 QPixmap p2(10, 10); |
|
245 p2.fill(Qt::yellow); |
|
246 |
|
247 // Calcuate estimated num of items what fits to cache |
|
248 int estimatedNum = (1024 * QPixmapCache::cacheLimit()) |
|
249 / ((p1.width() * p1.height() * p1.depth()) / 8); |
|
250 |
|
251 // Mare sure we will put enough items to reach the cache limit |
|
252 const int numberOfKeys = estimatedNum + 1000; |
|
253 |
|
254 // make sure it doesn't explode |
|
255 for (int i = 0; i < numberOfKeys; ++i) |
|
256 QPixmapCache::insert("0", p1); |
|
257 |
|
258 // ditto |
|
259 for (int j = 0; j < numberOfKeys; ++j) |
|
260 QPixmapCache::insert(QString::number(j), p1); |
|
261 |
|
262 int num = 0; |
|
263 for (int k = 0; k < numberOfKeys; ++k) { |
|
264 if (QPixmapCache::find(QString::number(k))) |
|
265 ++num; |
|
266 } |
|
267 |
|
268 if (QPixmapCache::find("0")) |
|
269 ++num; |
|
270 |
|
271 QVERIFY(num <= estimatedNum); |
|
272 QPixmap p3; |
|
273 QPixmapCache::insert("null", p3); |
|
274 |
|
275 QPixmap c1(10, 10); |
|
276 c1.fill(Qt::yellow); |
|
277 QPixmapCache::insert("custom", c1); |
|
278 QVERIFY(!c1.isDetached()); |
|
279 QPixmap c2(10, 10); |
|
280 c2.fill(Qt::red); |
|
281 QPixmapCache::insert("custom", c2); |
|
282 //We have deleted the old pixmap in the cache for the same key |
|
283 QVERIFY(c1.isDetached()); |
|
284 |
|
285 //The int part of the API |
|
286 // make sure it doesn't explode |
|
287 QList<QPixmapCache::Key> keys; |
|
288 for (int i = 0; i < numberOfKeys; ++i) |
|
289 keys.append(QPixmapCache::insert(p1)); |
|
290 |
|
291 num = 0; |
|
292 for (int k = 0; k < numberOfKeys; ++k) { |
|
293 if (QPixmapCache::find(keys.at(k), &p2)) |
|
294 ++num; |
|
295 } |
|
296 |
|
297 estimatedNum = (1024 * QPixmapCache::cacheLimit()) |
|
298 / ((p1.width() * p1.height() * p1.depth()) / 8); |
|
299 QVERIFY(num <= estimatedNum); |
|
300 } |
|
301 |
|
302 void tst_QPixmapCache::replace() |
|
303 { |
|
304 //The int part of the API |
|
305 QPixmap p1(10, 10); |
|
306 p1.fill(Qt::red); |
|
307 |
|
308 QPixmap p2(10, 10); |
|
309 p2.fill(Qt::yellow); |
|
310 |
|
311 QPixmapCache::Key key = QPixmapCache::insert(p1); |
|
312 QCOMPARE(getPrivate(key)->isValid, true); |
|
313 |
|
314 QPixmap p3; |
|
315 QVERIFY(QPixmapCache::find(key, &p3) == 1); |
|
316 |
|
317 QPixmapCache::replace(key, p2); |
|
318 |
|
319 QVERIFY(QPixmapCache::find(key, &p3) == 1); |
|
320 QCOMPARE(getPrivate(key)->isValid, true); |
|
321 QCOMPARE(getPrivate(key)->key, 1); |
|
322 |
|
323 QCOMPARE(p3.width(), 10); |
|
324 QCOMPARE(p3.height(), 10); |
|
325 QCOMPARE(p3, p2); |
|
326 |
|
327 //Broken keys |
|
328 QCOMPARE(QPixmapCache::replace(QPixmapCache::Key(), p2), false); |
|
329 } |
|
330 |
|
331 void tst_QPixmapCache::remove() |
|
332 { |
|
333 QPixmap p1(10, 10); |
|
334 p1.fill(Qt::red); |
|
335 |
|
336 QPixmapCache::insert("red", p1); |
|
337 p1.fill(Qt::yellow); |
|
338 |
|
339 QPixmap p2; |
|
340 QVERIFY(QPixmapCache::find("red", p2)); |
|
341 QVERIFY(p1.toImage() != p2.toImage()); |
|
342 QVERIFY(p1.toImage() == p1.toImage()); // sanity check |
|
343 |
|
344 QPixmapCache::remove("red"); |
|
345 QVERIFY(QPixmapCache::find("red") == 0); |
|
346 QPixmapCache::remove("red"); |
|
347 QVERIFY(QPixmapCache::find("red") == 0); |
|
348 |
|
349 QPixmapCache::remove("green"); |
|
350 QVERIFY(QPixmapCache::find("green") == 0); |
|
351 |
|
352 //The int part of the API |
|
353 QPixmapCache::clear(); |
|
354 p1.fill(Qt::red); |
|
355 QPixmapCache::Key key = QPixmapCache::insert(p1); |
|
356 p1.fill(Qt::yellow); |
|
357 |
|
358 QVERIFY(QPixmapCache::find(key, &p2)); |
|
359 QVERIFY(p1.toImage() != p2.toImage()); |
|
360 QVERIFY(p1.toImage() == p1.toImage()); // sanity check |
|
361 |
|
362 QPixmapCache::remove(key); |
|
363 QVERIFY(QPixmapCache::find(key, &p1) == 0); |
|
364 |
|
365 //Broken key |
|
366 QPixmapCache::remove(QPixmapCache::Key()); |
|
367 QVERIFY(QPixmapCache::find(QPixmapCache::Key(), &p1) == 0); |
|
368 |
|
369 //Test if keys are release |
|
370 QPixmapCache::clear(); |
|
371 key = QPixmapCache::insert(p1); |
|
372 QCOMPARE(getPrivate(key)->key, 1); |
|
373 QPixmapCache::remove(key); |
|
374 key = QPixmapCache::insert(p1); |
|
375 QCOMPARE(getPrivate(key)->key, 1); |
|
376 |
|
377 //Test if pixmaps are correctly deleted |
|
378 QPixmapCache::clear(); |
|
379 key = QPixmapCache::insert(p1); |
|
380 QCOMPARE(getPrivate(key)->key, 1); |
|
381 QVERIFY(QPixmapCache::find(key, &p1) != 0); |
|
382 QPixmapCache::remove(key); |
|
383 QCOMPARE(p1.isDetached(), true); |
|
384 |
|
385 //We mix both part of the API |
|
386 QPixmapCache::clear(); |
|
387 p1.fill(Qt::red); |
|
388 QPixmapCache::insert("red", p1); |
|
389 key = QPixmapCache::insert(p1); |
|
390 QPixmapCache::remove(key); |
|
391 QVERIFY(QPixmapCache::find(key, &p1) == 0); |
|
392 QVERIFY(QPixmapCache::find("red") != 0); |
|
393 } |
|
394 |
|
395 void tst_QPixmapCache::clear() |
|
396 { |
|
397 QPixmap p1(10, 10); |
|
398 p1.fill(Qt::red); |
|
399 |
|
400 // Calcuate estimated num of items what fits to cache |
|
401 int estimatedNum = (1024 * QPixmapCache::cacheLimit()) |
|
402 / ((p1.width() * p1.height() * p1.depth()) / 8); |
|
403 |
|
404 // Mare sure we will put enough items to reach the cache limit |
|
405 const int numberOfKeys = estimatedNum + 1000; |
|
406 |
|
407 for (int i = 0; i < numberOfKeys; ++i) |
|
408 QVERIFY(QPixmapCache::find("x" + QString::number(i)) == 0); |
|
409 |
|
410 for (int j = 0; j < numberOfKeys; ++j) |
|
411 QPixmapCache::insert(QString::number(j), p1); |
|
412 |
|
413 int num = 0; |
|
414 for (int k = 0; k < numberOfKeys; ++k) { |
|
415 if (QPixmapCache::find(QString::number(k), p1)) |
|
416 ++num; |
|
417 } |
|
418 QVERIFY(num > 0); |
|
419 |
|
420 QPixmapCache::clear(); |
|
421 |
|
422 for (int k = 0; k < numberOfKeys; ++k) |
|
423 QVERIFY(QPixmapCache::find(QString::number(k)) == 0); |
|
424 |
|
425 //The int part of the API |
|
426 QPixmap p2(10, 10); |
|
427 p2.fill(Qt::red); |
|
428 |
|
429 QList<QPixmapCache::Key> keys; |
|
430 for (int k = 0; k < numberOfKeys; ++k) |
|
431 keys.append(QPixmapCache::insert(p2)); |
|
432 |
|
433 QPixmapCache::clear(); |
|
434 |
|
435 for (int k = 0; k < numberOfKeys; ++k) { |
|
436 QVERIFY(QPixmapCache::find(keys.at(k), &p1) == 0); |
|
437 QCOMPARE(getPrivate(keys[k])->isValid, false); |
|
438 } |
|
439 } |
|
440 |
|
441 void tst_QPixmapCache::pixmapKey() |
|
442 { |
|
443 QPixmapCache::Key key; |
|
444 //Default constructed keys have no d pointer unless |
|
445 //we use them |
|
446 QVERIFY(!getPrivate(key)); |
|
447 //Let's put a d pointer |
|
448 QPixmapCache::KeyData** keyd = getPrivateRef(key); |
|
449 *keyd = new QPixmapCache::KeyData; |
|
450 QCOMPARE(getPrivate(key)->ref, 1); |
|
451 QPixmapCache::Key key2; |
|
452 //Let's put a d pointer |
|
453 QPixmapCache::KeyData** key2d = getPrivateRef(key2); |
|
454 *key2d = new QPixmapCache::KeyData; |
|
455 QCOMPARE(getPrivate(key2)->ref, 1); |
|
456 key = key2; |
|
457 QCOMPARE(getPrivate(key2)->ref, 2); |
|
458 QCOMPARE(getPrivate(key)->ref, 2); |
|
459 QPixmapCache::Key key3; |
|
460 //Let's put a d pointer |
|
461 QPixmapCache::KeyData** key3d = getPrivateRef(key3); |
|
462 *key3d = new QPixmapCache::KeyData; |
|
463 QPixmapCache::Key key4 = key3; |
|
464 QCOMPARE(getPrivate(key3)->ref, 2); |
|
465 QCOMPARE(getPrivate(key4)->ref, 2); |
|
466 key4 = key; |
|
467 QCOMPARE(getPrivate(key4)->ref, 3); |
|
468 QCOMPARE(getPrivate(key3)->ref, 1); |
|
469 QPixmapCache::Key key5(key3); |
|
470 QCOMPARE(getPrivate(key3)->ref, 2); |
|
471 QCOMPARE(getPrivate(key5)->ref, 2); |
|
472 |
|
473 //let test default constructed keys |
|
474 QPixmapCache::Key key6; |
|
475 QVERIFY(!getPrivate(key6)); |
|
476 QPixmapCache::Key key7; |
|
477 QVERIFY(!getPrivate(key7)); |
|
478 key6 = key7; |
|
479 QVERIFY(!getPrivate(key6)); |
|
480 QVERIFY(!getPrivate(key7)); |
|
481 QPixmapCache::Key key8(key7); |
|
482 QVERIFY(!getPrivate(key8)); |
|
483 } |
|
484 |
|
485 QTEST_MAIN(tst_QPixmapCache) |
|
486 #include "tst_qpixmapcache.moc" |