WinCairo build fails to link.
[WebKit-https.git] / Source / WebKit / chromium / tests / ImageDecodingStoreTest.cpp
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 "ImageDecodingStore.h"
29
30 #include "ImageFrameGenerator.h"
31 #include "MockDiscardablePixelRef.h"
32 #include "MockImageDecoder.h"
33 #include "SharedBuffer.h"
34 #include <gtest/gtest.h>
35
36 using namespace WebCore;
37
38 namespace {
39
40 class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderClient {
41 public:
42     virtual void SetUp()
43     {
44         ImageDecodingStore::initializeOnce();
45         m_data = SharedBuffer::create();
46         m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true);
47         m_decodersDestroyed = 0;
48     }
49
50     virtual void TearDown()
51     {
52         ImageDecodingStore::shutdown();
53     }
54
55     virtual void decoderBeingDestroyed()
56     {
57         ++m_decodersDestroyed;
58     }
59
60     virtual void frameBufferRequested()
61     {
62         // Decoder is never used by ImageDecodingStore.
63         ASSERT_TRUE(false);
64     }
65
66     virtual ImageFrame::FrameStatus frameStatus()
67     {
68         return ImageFrame::FramePartial;
69     }
70
71 protected:
72     PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false)
73     {
74         SkBitmap bitmap;
75         bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
76         if (!discardable)
77             bitmap.allocPixels();
78         else
79             bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
80         return ScaledImageFragment::create(size, bitmap, true);
81     }
82
83     PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false)
84     {
85         SkBitmap bitmap;
86         bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
87         if (!discardable)
88             bitmap.allocPixels();
89         else
90             bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
91         return ScaledImageFragment::create(size, bitmap, false);
92     }
93
94     void insertCache(const SkISize& size)
95     {
96         const ScaledImageFragment* image = ImageDecodingStore::instance()->insertAndLockCache(
97             m_generator.get(), createCompleteImage(size));
98         unlockCache(image);
99     }
100
101     const ScaledImageFragment* lockCache(const SkISize& size)
102     {
103         const ScaledImageFragment* cachedImage = 0;
104         if (ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage))
105             return cachedImage;
106         return 0;
107     }
108
109     void unlockCache(const ScaledImageFragment* cachedImage)
110     {
111         ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
112     }
113
114     void evictOneCache()
115     {
116         size_t memoryUsageInBytes = ImageDecodingStore::instance()->memoryUsageInBytes();
117         if (memoryUsageInBytes)
118             ImageDecodingStore::instance()->setCacheLimitInBytes(memoryUsageInBytes - 1);
119         else
120             ImageDecodingStore::instance()->setCacheLimitInBytes(0);
121     }
122
123     bool isCacheAlive(const SkISize& size)
124     {
125         const ScaledImageFragment* cachedImage = lockCache(size);
126         if (!cachedImage)
127             return false;
128         ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
129         return true;
130     }
131
132     RefPtr<SharedBuffer> m_data;
133     RefPtr<ImageFrameGenerator> m_generator;
134     int m_decodersDestroyed;
135 };
136
137 TEST_F(ImageDecodingStoreTest, evictOneCache)
138 {
139     insertCache(SkISize::Make(1, 1));
140     insertCache(SkISize::Make(2, 2));
141     insertCache(SkISize::Make(3, 3));
142     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
143
144     evictOneCache();
145     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
146
147     evictOneCache();
148     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
149 }
150
151 TEST_F(ImageDecodingStoreTest, pruneOrderIsLeastRecentlyUsed)
152 {
153     insertCache(SkISize::Make(1, 1));
154     insertCache(SkISize::Make(2, 2));
155     insertCache(SkISize::Make(3, 3));
156     insertCache(SkISize::Make(4, 4));
157     insertCache(SkISize::Make(5, 5));
158     EXPECT_EQ(5u, ImageDecodingStore::instance()->cacheEntries());
159
160     // Use cache in the order 3, 2, 4, 1, 5.
161     EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3)));
162     EXPECT_TRUE(isCacheAlive(SkISize::Make(2, 2)));
163     EXPECT_TRUE(isCacheAlive(SkISize::Make(4, 4)));
164     EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1)));
165     EXPECT_TRUE(isCacheAlive(SkISize::Make(5, 5)));
166
167     // Evict 3.
168     evictOneCache();
169     EXPECT_FALSE(isCacheAlive(SkISize::Make(3, 3)));
170     EXPECT_EQ(4u, ImageDecodingStore::instance()->cacheEntries());
171
172     // Evict 2.
173     evictOneCache();
174     EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2)));
175     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
176
177     // Evict 4.
178     evictOneCache();
179     EXPECT_FALSE(isCacheAlive(SkISize::Make(4, 4)));
180     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
181
182     // Evict 1.
183     evictOneCache();
184     EXPECT_FALSE(isCacheAlive(SkISize::Make(1, 1)));
185     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
186
187     // Evict 5.
188     evictOneCache();
189     EXPECT_FALSE(isCacheAlive(SkISize::Make(5, 5)));
190     EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries());
191 }
192
193 TEST_F(ImageDecodingStoreTest, pruneCausedByInsertion)
194 {
195     ImageDecodingStore::instance()->setCacheLimitInBytes(100);
196
197     // Insert 100 entries.
198     // Cache entries stored should increase and eventually decrease to 1.
199     insertCache(SkISize::Make(1, 1));
200     insertCache(SkISize::Make(2, 2));
201     insertCache(SkISize::Make(3, 3));
202     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
203
204     for (int i = 4; i <= 100; ++i)
205         insertCache(SkISize::Make(i, i));
206
207     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
208     for (int i = 1; i <= 99; ++i)
209         EXPECT_FALSE(isCacheAlive(SkISize::Make(i, i)));
210     EXPECT_TRUE(isCacheAlive(SkISize::Make(100, 100)));
211 }
212
213 TEST_F(ImageDecodingStoreTest, cacheInUseNotEvicted)
214 {
215     insertCache(SkISize::Make(1, 1));
216     insertCache(SkISize::Make(2, 2));
217     insertCache(SkISize::Make(3, 3));
218     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
219
220     const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1));
221     ASSERT_TRUE(cachedImage);
222
223     // Cache 2 is evicted because cache 1 is in use.
224     evictOneCache();
225     EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1)));
226     EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2)));
227     EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3)));
228
229     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
230     unlockCache(cachedImage);
231 }
232
233 TEST_F(ImageDecodingStoreTest, destroyImageFrameGenerator)
234 {
235     insertCache(SkISize::Make(1, 1));
236     insertCache(SkISize::Make(2, 2));
237     insertCache(SkISize::Make(3, 3));
238     EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries());
239
240     m_generator.clear();
241     EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
242 }
243
244 TEST_F(ImageDecodingStoreTest, insertIncompleteCache)
245 {
246     const SkISize size = SkISize::Make(1, 1);
247     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
248         m_generator.get(), createIncompleteImage(size), MockImageDecoder::create(this));
249     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
250     unlockCache(cachedImage);
251
252     ImageDecoder* decoder = 0;
253     EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &decoder));
254     EXPECT_TRUE(decoder);
255     ASSERT_TRUE(cachedImage);
256     EXPECT_FALSE(cachedImage->isComplete());
257     unlockCache(cachedImage);
258     EXPECT_EQ(0, m_decodersDestroyed);
259 }
260
261 TEST_F(ImageDecodingStoreTest, insertCompleteCacheWithDecoder)
262 {
263     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
264         m_generator.get(), createCompleteImage(SkISize::Make(1, 1)), MockImageDecoder::create(this));
265     unlockCache(cachedImage);
266     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
267     EXPECT_EQ(1, m_decodersDestroyed);
268 }
269
270 TEST_F(ImageDecodingStoreTest, incompleteCacheBecomesComplete)
271 {
272     const SkISize size = SkISize::Make(1, 1);
273     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
274         m_generator.get(), createIncompleteImage(size), MockImageDecoder::create(this));
275     ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
276     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
277
278     ImageDecoder* decoder = 0;
279     EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &decoder));
280     EXPECT_TRUE(decoder);
281     ASSERT_TRUE(cachedImage);
282     EXPECT_FALSE(cachedImage->isComplete());
283
284     cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(
285         m_generator.get(), cachedImage, createCompleteImage(size));
286     EXPECT_TRUE(cachedImage->isComplete());
287     EXPECT_EQ(1, m_decodersDestroyed);
288     ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
289 }
290
291 TEST_F(ImageDecodingStoreTest, lockCacheFailedAfterMemoryDiscarded)
292 {
293     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
294         m_generator.get(), createCompleteImage(SkISize::Make(1, 1), true), MockImageDecoder::create(this));
295     unlockCache(cachedImage);
296     MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(cachedImage->bitmap().pixelRef());
297     pixelRef->discard();
298     EXPECT_EQ(0, lockCache(SkISize::Make(1, 1)));
299     EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries());
300 }
301
302 TEST_F(ImageDecodingStoreTest, overwriteNonDiscardableCacheWithDiscardable)
303 {
304
305     const SkISize size = SkISize::Make(1, 1);
306     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
307         m_generator.get(), createIncompleteImage(size), MockImageDecoder::create(this));
308     ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
309     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
310     EXPECT_LT(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
311
312     ImageDecoder* decoder = 0;
313     EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &decoder));
314     EXPECT_FALSE(cachedImage->isComplete());
315
316     cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(
317         m_generator.get(), cachedImage, createCompleteImage(size, true));
318     EXPECT_TRUE(cachedImage->isComplete());
319     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
320     EXPECT_EQ(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
321     ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
322 }
323
324 TEST_F(ImageDecodingStoreTest, overwriteDiscardableCacheWithNonDiscardable)
325 {
326
327     const SkISize size = SkISize::Make(1, 1);
328     const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
329         m_generator.get(), createIncompleteImage(size, true), MockImageDecoder::create(this));
330     ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
331     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
332     EXPECT_EQ(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
333
334     ImageDecoder* decoder = 0;
335     EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &decoder));
336     EXPECT_FALSE(cachedImage->isComplete());
337
338     cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(
339         m_generator.get(), cachedImage, createCompleteImage(size));
340     EXPECT_TRUE(cachedImage->isComplete());
341     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
342     EXPECT_LT(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
343     ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
344 }
345
346 } // namespace