1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include "platform/graphics/ImageDecodingStore.h"
29
30#include "platform/SharedBuffer.h"
31#include "platform/graphics/ImageFrameGenerator.h"
32#include "platform/graphics/test/MockDiscardablePixelRef.h"
33#include "platform/graphics/test/MockImageDecoder.h"
34#include <gtest/gtest.h>
35
36using namespace WebCore;
37
38namespace {
39
40class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderClient {
41public:
42    virtual void SetUp()
43    {
44        ImageDecodingStore::initializeOnce();
45        ImageDecodingStore::instance()->setImageCachingEnabled(true);
46        m_data = SharedBuffer::create();
47        m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true);
48        m_decodersDestroyed = 0;
49    }
50
51    virtual void TearDown()
52    {
53        ImageDecodingStore::shutdown();
54    }
55
56    virtual void decoderBeingDestroyed()
57    {
58        ++m_decodersDestroyed;
59    }
60
61    virtual void frameBufferRequested()
62    {
63        // Decoder is never used by ImageDecodingStore.
64        ASSERT_TRUE(false);
65    }
66
67    virtual ImageFrame::Status status()
68    {
69        return ImageFrame::FramePartial;
70    }
71
72    virtual size_t frameCount() { return 1; }
73    virtual int repetitionCount() const { return cAnimationNone; }
74    virtual float frameDuration() const { return 0; }
75
76protected:
77    PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false, size_t index = 0)
78    {
79        SkBitmap bitmap;
80        bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
81        if (!discardable)
82            bitmap.allocPixels();
83        else
84            bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
85        return ScaledImageFragment::createComplete(size, index, bitmap);
86    }
87
88    PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false, size_t generation = 0)
89    {
90        SkBitmap bitmap;
91        bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
92        if (!discardable)
93            bitmap.allocPixels();
94        else
95            bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
96        return ScaledImageFragment::createPartial(size, 0, generation, bitmap);
97    }
98
99    void insertCache(const SkISize& size)
100    {
101        const ScaledImageFragment* image = ImageDecodingStore::instance()->insertAndLockCache(
102            m_generator.get(), createCompleteImage(size));
103        unlockCache(image);
104    }
105
106    const ScaledImageFragment* lockCache(const SkISize& size, size_t index = 0)
107    {
108        const ScaledImageFragment* cachedImage = 0;
109        if (ImageDecodingStore::instance()->lockCache(m_generator.get(), size, index, &cachedImage))
110            return cachedImage;
111        return 0;
112    }
113
114    void unlockCache(const ScaledImageFragment* cachedImage)
115    {
116        ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
117    }
118
119    void evictOneCache()
120    {
121        size_t memoryUsageInBytes = ImageDecodingStore::instance()->memoryUsageInBytes();
122        if (memoryUsageInBytes)
123            ImageDecodingStore::instance()->setCacheLimitInBytes(memoryUsageInBytes - 1);
124        else
125            ImageDecodingStore::instance()->setCacheLimitInBytes(0);
126    }
127
128    bool isCacheAlive(const SkISize& size)
129    {
130        const ScaledImageFragment* cachedImage = lockCache(size);
131        if (!cachedImage)
132            return false;
133        ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
134        return true;
135    }
136
137    RefPtr<SharedBuffer> m_data;
138    RefPtr<ImageFrameGenerator> m_generator;
139    int m_decodersDestroyed;
140};
141
142TEST_F(ImageDecodingStoreTest, evictOneCache)
143{
144    insertCache(SkISize::Make(1, 1));
145    insertCache(SkISize::Make(2, 2));
146    insertCache(SkISize::Make(3, 3));
147    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
148
149    evictOneCache();
150    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
151
152    evictOneCache();
153    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
154}
155
156TEST_F(ImageDecodingStoreTest, pruneOrderIsLeastRecentlyUsed)
157{
158    insertCache(SkISize::Make(1, 1));
159    insertCache(SkISize::Make(2, 2));
160    insertCache(SkISize::Make(3, 3));
161    insertCache(SkISize::Make(4, 4));
162    insertCache(SkISize::Make(5, 5));
163    EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries());
164
165    // Use cache in the order 3, 2, 4, 1, 5.
166    EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3)));
167    EXPECT_TRUE(isCacheAlive(SkISize::Make(2, 2)));
168    EXPECT_TRUE(isCacheAlive(SkISize::Make(4, 4)));
169    EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1)));
170    EXPECT_TRUE(isCacheAlive(SkISize::Make(5, 5)));
171
172    // Evict 3.
173    evictOneCache();
174    EXPECT_FALSE(isCacheAlive(SkISize::Make(3, 3)));
175    EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries());
176
177    // Evict 2.
178    evictOneCache();
179    EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2)));
180    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
181
182    // Evict 4.
183    evictOneCache();
184    EXPECT_FALSE(isCacheAlive(SkISize::Make(4, 4)));
185    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
186
187    // Evict 1.
188    evictOneCache();
189    EXPECT_FALSE(isCacheAlive(SkISize::Make(1, 1)));
190    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
191
192    // Evict 5.
193    evictOneCache();
194    EXPECT_FALSE(isCacheAlive(SkISize::Make(5, 5)));
195    EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries());
196}
197
198TEST_F(ImageDecodingStoreTest, pruneCausedByInsertion)
199{
200    ImageDecodingStore::instance()->setCacheLimitInBytes(100);
201
202    // Insert 100 entries.
203    // Cache entries stored should increase and eventually decrease to 1.
204    insertCache(SkISize::Make(1, 1));
205    insertCache(SkISize::Make(2, 2));
206    insertCache(SkISize::Make(3, 3));
207    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
208
209    for (int i = 4; i <= 100; ++i)
210        insertCache(SkISize::Make(i, i));
211
212    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
213    for (int i = 1; i <= 99; ++i)
214        EXPECT_FALSE(isCacheAlive(SkISize::Make(i, i)));
215    EXPECT_TRUE(isCacheAlive(SkISize::Make(100, 100)));
216}
217
218TEST_F(ImageDecodingStoreTest, cacheInUseNotEvicted)
219{
220    insertCache(SkISize::Make(1, 1));
221    insertCache(SkISize::Make(2, 2));
222    insertCache(SkISize::Make(3, 3));
223    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
224
225    const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1));
226    ASSERT_TRUE(cachedImage);
227
228    // Cache 2 is evicted because cache 1 is in use.
229    evictOneCache();
230    EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1)));
231    EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2)));
232    EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3)));
233
234    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
235    unlockCache(cachedImage);
236}
237
238TEST_F(ImageDecodingStoreTest, destroyImageFrameGenerator)
239{
240    insertCache(SkISize::Make(1, 1));
241    insertCache(SkISize::Make(2, 2));
242    insertCache(SkISize::Make(3, 3));
243    OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
244    decoder->setSize(1, 1);
245    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
246    EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries());
247
248    m_generator.clear();
249    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
250}
251
252TEST_F(ImageDecodingStoreTest, insertDecoder)
253{
254    const SkISize size = SkISize::Make(1, 1);
255    OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
256    decoder->setSize(1, 1);
257    const ImageDecoder* refDecoder = decoder.get();
258    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
259    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
260    EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes());
261
262    ImageDecoder* testDecoder;
263    EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
264    EXPECT_TRUE(testDecoder);
265    EXPECT_EQ(refDecoder, testDecoder);
266    ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder);
267    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
268}
269
270TEST_F(ImageDecodingStoreTest, evictDecoder)
271{
272    OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this);
273    OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this);
274    OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this);
275    decoder1->setSize(1, 1);
276    decoder2->setSize(2, 2);
277    decoder3->setSize(3, 3);
278    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false);
279    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false);
280    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false);
281    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
282    EXPECT_EQ(56u, ImageDecodingStore::instance()->memoryUsageInBytes());
283
284    evictOneCache();
285    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
286    EXPECT_EQ(52u, ImageDecodingStore::instance()->memoryUsageInBytes());
287
288    evictOneCache();
289    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
290    EXPECT_EQ(36u, ImageDecodingStore::instance()->memoryUsageInBytes());
291
292    evictOneCache();
293    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
294    EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes());
295}
296
297TEST_F(ImageDecodingStoreTest, decoderInUseNotEvicted)
298{
299    OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this);
300    OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this);
301    OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this);
302    decoder1->setSize(1, 1);
303    decoder2->setSize(2, 2);
304    decoder3->setSize(3, 3);
305    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false);
306    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false);
307    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false);
308    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
309
310    ImageDecoder* testDecoder;
311    EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), SkISize::Make(2, 2), &testDecoder));
312
313    evictOneCache();
314    evictOneCache();
315    evictOneCache();
316    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
317    EXPECT_EQ(16u, ImageDecodingStore::instance()->memoryUsageInBytes());
318
319    ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder);
320    evictOneCache();
321    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
322    EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes());
323}
324
325TEST_F(ImageDecodingStoreTest, removeDecoder)
326{
327    const SkISize size = SkISize::Make(1, 1);
328    OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
329    decoder->setSize(1, 1);
330    const ImageDecoder* refDecoder = decoder.get();
331    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
332    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
333    EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes());
334
335    ImageDecoder* testDecoder;
336    EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
337    EXPECT_TRUE(testDecoder);
338    EXPECT_EQ(refDecoder, testDecoder);
339    ImageDecodingStore::instance()->removeDecoder(m_generator.get(), testDecoder);
340    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
341
342    EXPECT_FALSE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
343}
344
345TEST_F(ImageDecodingStoreTest, multipleIndex)
346{
347    const SkISize size = SkISize::Make(1, 1);
348    const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
349        m_generator.get(), createCompleteImage(size, false, 0));
350    unlockCache(refImage);
351    const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
352        m_generator.get(), createCompleteImage(size, false, 1));
353    unlockCache(testImage);
354    EXPECT_NE(refImage, testImage);
355    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
356
357    EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 1, &refImage));
358    EXPECT_EQ(refImage, testImage);
359    unlockCache(refImage);
360}
361
362TEST_F(ImageDecodingStoreTest, finalAndPartialImage)
363{
364    const SkISize size = SkISize::Make(1, 1);
365    const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
366        m_generator.get(), createCompleteImage(size, false, 0));
367    unlockCache(refImage);
368    const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
369        m_generator.get(), createIncompleteImage(size, false, 1));
370    unlockCache(testImage);
371    EXPECT_NE(refImage, testImage);
372    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
373
374    EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 0, &refImage));
375    EXPECT_NE(refImage, testImage);
376    unlockCache(refImage);
377}
378
379TEST_F(ImageDecodingStoreTest, insertNoGenerationCollision)
380{
381    const SkISize size = SkISize::Make(1, 1);
382    const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
383        m_generator.get(), createIncompleteImage(size, false, 1));
384    unlockCache(refImage);
385    const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
386        m_generator.get(), createIncompleteImage(size, false, 2));
387    unlockCache(testImage);
388    EXPECT_NE(refImage, testImage);
389    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
390}
391
392TEST_F(ImageDecodingStoreTest, insertGenerationCollision)
393{
394    const SkISize size = SkISize::Make(1, 1);
395    const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
396        m_generator.get(), createIncompleteImage(size, false, 1));
397    unlockCache(refImage);
398    const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
399        m_generator.get(), createIncompleteImage(size, false, 1));
400    unlockCache(testImage);
401    EXPECT_EQ(refImage, testImage);
402    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
403}
404
405TEST_F(ImageDecodingStoreTest, insertGenerationCollisionAfterMemoryDiscarded)
406{
407    const SkISize size = SkISize::Make(1, 1);
408    const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache(
409        m_generator.get(), createIncompleteImage(size, true, 1));
410    unlockCache(refImage);
411    MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(refImage->bitmap().pixelRef());
412    pixelRef->discard();
413    const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache(
414        m_generator.get(), createIncompleteImage(size, false, 1));
415    unlockCache(testImage);
416    EXPECT_NE(refImage, testImage);
417    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
418}
419
420TEST_F(ImageDecodingStoreTest, lockCacheFailedAfterMemoryDiscarded)
421{
422    const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
423        m_generator.get(), createCompleteImage(SkISize::Make(1, 1), true));
424    unlockCache(cachedImage);
425    MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(cachedImage->bitmap().pixelRef());
426    pixelRef->discard();
427    EXPECT_EQ(0, lockCache(SkISize::Make(1, 1)));
428    EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries());
429}
430
431TEST_F(ImageDecodingStoreTest, clear)
432{
433    insertCache(SkISize::Make(1, 1));
434    insertCache(SkISize::Make(2, 2));
435    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
436
437    OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
438    decoder->setSize(1, 1);
439    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false);
440    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
441
442    ImageDecodingStore::instance()->clear();
443    EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries());
444}
445
446TEST_F(ImageDecodingStoreTest, clearInUse)
447{
448    insertCache(SkISize::Make(1, 1));
449    insertCache(SkISize::Make(2, 2));
450    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
451
452    const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1));
453    ASSERT_TRUE(cachedImage);
454    ImageDecodingStore::instance()->clear();
455    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
456
457    unlockCache(cachedImage);
458    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
459}
460
461TEST_F(ImageDecodingStoreTest, disableImageCaching)
462{
463    ImageDecodingStore::instance()->setImageCachingEnabled(false);
464    insertCache(SkISize::Make(1, 1));
465    insertCache(SkISize::Make(2, 2));
466    EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries());
467
468    const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
469        m_generator.get(), createCompleteImage(SkISize::Make(3, 3), true));
470    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
471    unlockCache(cachedImage);
472    EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries());
473}
474
475} // namespace
476