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/MockImageDecoder.h"
33#include <gtest/gtest.h>
34
35using namespace blink;
36
37namespace {
38
39class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderClient {
40public:
41    virtual void SetUp()
42    {
43        ImageDecodingStore::instance()->setCacheLimitInBytes(1024 * 1024);
44        m_data = SharedBuffer::create();
45        m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true);
46        m_decodersDestroyed = 0;
47    }
48
49    virtual void TearDown()
50    {
51        ImageDecodingStore::instance()->clear();
52    }
53
54    virtual void decoderBeingDestroyed()
55    {
56        ++m_decodersDestroyed;
57    }
58
59    virtual void frameBufferRequested()
60    {
61        // Decoder is never used by ImageDecodingStore.
62        ASSERT_TRUE(false);
63    }
64
65    virtual ImageFrame::Status status()
66    {
67        return ImageFrame::FramePartial;
68    }
69
70    virtual size_t frameCount() { return 1; }
71    virtual int repetitionCount() const { return cAnimationNone; }
72    virtual float frameDuration() const { return 0; }
73
74protected:
75    void evictOneCache()
76    {
77        size_t memoryUsageInBytes = ImageDecodingStore::instance()->memoryUsageInBytes();
78        if (memoryUsageInBytes)
79            ImageDecodingStore::instance()->setCacheLimitInBytes(memoryUsageInBytes - 1);
80        else
81            ImageDecodingStore::instance()->setCacheLimitInBytes(0);
82    }
83
84    RefPtr<SharedBuffer> m_data;
85    RefPtr<ImageFrameGenerator> m_generator;
86    int m_decodersDestroyed;
87};
88
89TEST_F(ImageDecodingStoreTest, insertDecoder)
90{
91    const SkISize size = SkISize::Make(1, 1);
92    OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
93    decoder->setSize(1, 1);
94    const ImageDecoder* refDecoder = decoder.get();
95    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release());
96    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
97    EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes());
98
99    ImageDecoder* testDecoder;
100    EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
101    EXPECT_TRUE(testDecoder);
102    EXPECT_EQ(refDecoder, testDecoder);
103    ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder);
104    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
105}
106
107TEST_F(ImageDecodingStoreTest, evictDecoder)
108{
109    OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this);
110    OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this);
111    OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this);
112    decoder1->setSize(1, 1);
113    decoder2->setSize(2, 2);
114    decoder3->setSize(3, 3);
115    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release());
116    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release());
117    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release());
118    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
119    EXPECT_EQ(56u, ImageDecodingStore::instance()->memoryUsageInBytes());
120
121    evictOneCache();
122    EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
123    EXPECT_EQ(52u, ImageDecodingStore::instance()->memoryUsageInBytes());
124
125    evictOneCache();
126    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
127    EXPECT_EQ(36u, ImageDecodingStore::instance()->memoryUsageInBytes());
128
129    evictOneCache();
130    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
131    EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes());
132}
133
134TEST_F(ImageDecodingStoreTest, decoderInUseNotEvicted)
135{
136    OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this);
137    OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this);
138    OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this);
139    decoder1->setSize(1, 1);
140    decoder2->setSize(2, 2);
141    decoder3->setSize(3, 3);
142    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release());
143    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release());
144    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release());
145    EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
146
147    ImageDecoder* testDecoder;
148    EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), SkISize::Make(2, 2), &testDecoder));
149
150    evictOneCache();
151    evictOneCache();
152    evictOneCache();
153    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
154    EXPECT_EQ(16u, ImageDecodingStore::instance()->memoryUsageInBytes());
155
156    ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder);
157    evictOneCache();
158    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
159    EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes());
160}
161
162TEST_F(ImageDecodingStoreTest, removeDecoder)
163{
164    const SkISize size = SkISize::Make(1, 1);
165    OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this);
166    decoder->setSize(1, 1);
167    const ImageDecoder* refDecoder = decoder.get();
168    ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release());
169    EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries());
170    EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes());
171
172    ImageDecoder* testDecoder;
173    EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
174    EXPECT_TRUE(testDecoder);
175    EXPECT_EQ(refDecoder, testDecoder);
176    ImageDecodingStore::instance()->removeDecoder(m_generator.get(), testDecoder);
177    EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries());
178
179    EXPECT_FALSE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder));
180}
181
182} // namespace
183