Home | History | Annotate | Download | only in graphics
      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 #include "platform/graphics/ImageFrameGenerator.h"
     28 
     29 #include "platform/SharedBuffer.h"
     30 #include "platform/Task.h"
     31 #include "platform/graphics/ImageDecodingStore.h"
     32 #include "platform/graphics/test/MockImageDecoder.h"
     33 #include "public/platform/Platform.h"
     34 #include "public/platform/WebThread.h"
     35 #include <gtest/gtest.h>
     36 
     37 namespace WebCore {
     38 
     39 namespace {
     40 
     41 // Helper methods to generate standard sizes.
     42 SkISize fullSize() { return SkISize::Make(100, 100); }
     43 SkISize scaledSize() { return SkISize::Make(50, 50); }
     44 
     45 } // namespace
     46 
     47 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient {
     48 public:
     49     virtual void SetUp() OVERRIDE
     50     {
     51         ImageDecodingStore::initializeOnce();
     52         ImageDecodingStore::instance()->setImageCachingEnabled(true);
     53         m_data = SharedBuffer::create();
     54         m_generator = ImageFrameGenerator::create(fullSize(), m_data, true);
     55         useMockImageDecoderFactory();
     56         m_decodersDestroyed = 0;
     57         m_frameBufferRequestCount = 0;
     58         m_status = ImageFrame::FrameEmpty;
     59     }
     60 
     61     virtual void TearDown() OVERRIDE
     62     {
     63         ImageDecodingStore::shutdown();
     64     }
     65 
     66     virtual void decoderBeingDestroyed() OVERRIDE
     67     {
     68         ++m_decodersDestroyed;
     69     }
     70 
     71     virtual void frameBufferRequested() OVERRIDE
     72     {
     73         ++m_frameBufferRequestCount;
     74     }
     75 
     76     virtual ImageFrame::Status status() OVERRIDE
     77     {
     78         ImageFrame::Status currentStatus = m_status;
     79         m_status = m_nextFrameStatus;
     80         return currentStatus;
     81     }
     82 
     83     virtual size_t frameCount() OVERRIDE { return 1; }
     84     virtual int repetitionCount() const OVERRIDE { return cAnimationNone; }
     85     virtual float frameDuration() const OVERRIDE { return 0; }
     86 
     87 protected:
     88     void useMockImageDecoderFactory()
     89     {
     90         m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this, fullSize()));
     91     }
     92 
     93     PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size)
     94     {
     95         SkBitmap bitmap;
     96         bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
     97         bitmap.allocPixels();
     98         return ScaledImageFragment::createComplete(size, 0, bitmap);
     99     }
    100 
    101     void addNewData()
    102     {
    103         m_data->append("g", 1);
    104         m_generator->setData(m_data, false);
    105     }
    106 
    107     void setFrameStatus(ImageFrame::Status status)  { m_status = m_nextFrameStatus = status; }
    108     void setNextFrameStatus(ImageFrame::Status status)  { m_nextFrameStatus = status; }
    109 
    110     SkBitmap::Allocator* allocator() const { return m_generator->allocator(); }
    111     void setAllocator(PassOwnPtr<SkBitmap::Allocator> allocator)
    112     {
    113         m_generator->setAllocator(allocator);
    114     }
    115 
    116     PassOwnPtr<ScaledImageFragment> decode(size_t index)
    117     {
    118         ImageDecoder* decoder = 0;
    119         return m_generator->decode(index, &decoder);
    120     }
    121 
    122     RefPtr<SharedBuffer> m_data;
    123     RefPtr<ImageFrameGenerator> m_generator;
    124     int m_decodersDestroyed;
    125     int m_frameBufferRequestCount;
    126     ImageFrame::Status m_status;
    127     ImageFrame::Status m_nextFrameStatus;
    128 };
    129 
    130 TEST_F(ImageFrameGeneratorTest, cacheHit)
    131 {
    132     const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
    133         m_generator.get(), createCompleteImage(fullSize()));
    134     EXPECT_EQ(fullSize(), fullImage->scaledSize());
    135     ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
    136 
    137     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
    138     EXPECT_EQ(fullImage, tempImage);
    139     EXPECT_EQ(fullSize(), tempImage->scaledSize());
    140     EXPECT_TRUE(m_generator->hasAlpha(0));
    141     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    142     EXPECT_EQ(0, m_frameBufferRequestCount);
    143 }
    144 
    145 TEST_F(ImageFrameGeneratorTest, cacheMissWithScale)
    146 {
    147     const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
    148         m_generator.get(), createCompleteImage(fullSize()));
    149     EXPECT_EQ(fullSize(), fullImage->scaledSize());
    150     ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
    151 
    152     // Cache miss because of scaled size not found.
    153     const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
    154     EXPECT_NE(fullImage, scaledImage);
    155     EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
    156     EXPECT_TRUE(m_generator->hasAlpha(0));
    157     ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
    158 
    159     // Cache hit.
    160     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
    161     EXPECT_EQ(scaledImage, tempImage);
    162     EXPECT_EQ(scaledSize(), tempImage->scaledSize());
    163     EXPECT_TRUE(m_generator->hasAlpha(0));
    164     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    165     EXPECT_EQ(0, m_frameBufferRequestCount);
    166 }
    167 
    168 TEST_F(ImageFrameGeneratorTest, cacheMissWithDecodeAndScale)
    169 {
    170     setFrameStatus(ImageFrame::FrameComplete);
    171 
    172     // Cache miss.
    173     const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
    174     EXPECT_EQ(1, m_frameBufferRequestCount);
    175     EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
    176     EXPECT_FALSE(m_generator->hasAlpha(0));
    177     ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
    178     EXPECT_EQ(1, m_decodersDestroyed);
    179 
    180     // Cache hit.
    181     const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize());
    182     EXPECT_NE(scaledImage, fullImage);
    183     EXPECT_EQ(fullSize(), fullImage->scaledSize());
    184     EXPECT_FALSE(m_generator->hasAlpha(0));
    185     ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
    186 
    187     // Cache hit.
    188     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
    189     EXPECT_EQ(scaledImage, tempImage);
    190     EXPECT_EQ(scaledSize(), tempImage->scaledSize());
    191     EXPECT_FALSE(m_generator->hasAlpha(0));
    192     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    193     EXPECT_EQ(1, m_frameBufferRequestCount);
    194 }
    195 
    196 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
    197 {
    198     setFrameStatus(ImageFrame::FramePartial);
    199 
    200     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
    201     EXPECT_FALSE(tempImage->isComplete());
    202     EXPECT_EQ(1, m_frameBufferRequestCount);
    203     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    204     EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
    205     EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
    206     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    207 
    208     addNewData();
    209     tempImage = m_generator->decodeAndScale(fullSize());
    210     EXPECT_FALSE(tempImage->isComplete());
    211     EXPECT_EQ(2, m_frameBufferRequestCount);
    212     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    213     EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
    214     EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
    215     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    216     EXPECT_EQ(0, m_decodersDestroyed);
    217 }
    218 
    219 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecodeAndScale)
    220 {
    221     setFrameStatus(ImageFrame::FramePartial);
    222 
    223     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(scaledSize());
    224     EXPECT_FALSE(tempImage->isComplete());
    225     EXPECT_EQ(1, m_frameBufferRequestCount);
    226     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    227     EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
    228     EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
    229     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    230 
    231     addNewData();
    232     tempImage = m_generator->decodeAndScale(scaledSize());
    233     EXPECT_FALSE(tempImage->isComplete());
    234     EXPECT_EQ(2, m_frameBufferRequestCount);
    235     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    236     EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries());
    237     EXPECT_EQ(4, ImageDecodingStore::instance()->imageCacheEntries());
    238     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    239     EXPECT_EQ(0, m_decodersDestroyed);
    240 }
    241 
    242 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
    243 {
    244     setFrameStatus(ImageFrame::FramePartial);
    245 
    246     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
    247     EXPECT_FALSE(tempImage->isComplete());
    248     EXPECT_EQ(1, m_frameBufferRequestCount);
    249     EXPECT_EQ(0, m_decodersDestroyed);
    250     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    251     EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
    252     EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
    253     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    254 
    255     setFrameStatus(ImageFrame::FrameComplete);
    256     addNewData();
    257 
    258     tempImage = m_generator->decodeAndScale(fullSize());
    259     EXPECT_TRUE(tempImage->isComplete());
    260     EXPECT_EQ(2, m_frameBufferRequestCount);
    261     EXPECT_EQ(1, m_decodersDestroyed);
    262     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    263     EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
    264     EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
    265     EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
    266 
    267     tempImage = m_generator->decodeAndScale(fullSize());
    268     EXPECT_TRUE(tempImage->isComplete());
    269     EXPECT_EQ(2, m_frameBufferRequestCount);
    270     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    271 }
    272 
    273 TEST_F(ImageFrameGeneratorTest, incompleteDecodeAndScaleBecomesComplete)
    274 {
    275     setFrameStatus(ImageFrame::FramePartial);
    276 
    277     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
    278     EXPECT_FALSE(tempImage->isComplete());
    279     EXPECT_EQ(1, m_frameBufferRequestCount);
    280     EXPECT_EQ(0, m_decodersDestroyed);
    281     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    282     EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
    283     EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
    284     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    285 
    286     setFrameStatus(ImageFrame::FrameComplete);
    287     addNewData();
    288 
    289     tempImage = m_generator->decodeAndScale(scaledSize());
    290     EXPECT_TRUE(tempImage->isComplete());
    291     EXPECT_EQ(2, m_frameBufferRequestCount);
    292     EXPECT_EQ(1, m_decodersDestroyed);
    293     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    294     EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries());
    295     EXPECT_EQ(4, ImageDecodingStore::instance()->imageCacheEntries());
    296     EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
    297 
    298     tempImage = m_generator->decodeAndScale(scaledSize());
    299     EXPECT_TRUE(tempImage->isComplete());
    300     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    301 
    302     tempImage = m_generator->decodeAndScale(fullSize());
    303     EXPECT_TRUE(tempImage->isComplete());
    304     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    305 
    306     EXPECT_EQ(2, m_frameBufferRequestCount);
    307 }
    308 
    309 static void decodeThreadMain(ImageFrameGenerator* generator)
    310 {
    311     const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
    312     ImageDecodingStore::instance()->unlockCache(generator, tempImage);
    313 }
    314 
    315 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
    316 {
    317     setFrameStatus(ImageFrame::FramePartial);
    318 
    319     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
    320     EXPECT_FALSE(tempImage->isComplete());
    321     EXPECT_EQ(1, m_frameBufferRequestCount);
    322     EXPECT_EQ(0, m_decodersDestroyed);
    323     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    324     EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
    325     EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
    326     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    327 
    328     // Frame can now be decoded completely.
    329     setFrameStatus(ImageFrame::FrameComplete);
    330     addNewData();
    331     OwnPtr<blink::WebThread> thread = adoptPtr(blink::Platform::current()->createThread("DecodeThread"));
    332     thread->postTask(new Task(WTF::bind(&decodeThreadMain, m_generator.get())));
    333     thread.clear();
    334 
    335     EXPECT_EQ(2, m_frameBufferRequestCount);
    336     EXPECT_EQ(1, m_decodersDestroyed);
    337     EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
    338     EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
    339     EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
    340 
    341     tempImage = m_generator->decodeAndScale(fullSize());
    342     EXPECT_TRUE(tempImage->isComplete());
    343     EXPECT_EQ(2, m_frameBufferRequestCount);
    344     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    345 }
    346 
    347 TEST_F(ImageFrameGeneratorTest, concurrentIncompleteDecodeAndScale)
    348 {
    349     setFrameStatus(ImageFrame::FramePartial);
    350 
    351     const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize());
    352     const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
    353     EXPECT_FALSE(fullImage->isComplete());
    354     EXPECT_FALSE(scaledImage->isComplete());
    355     EXPECT_EQ(2, m_frameBufferRequestCount);
    356     ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
    357     ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
    358     EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries());
    359     EXPECT_EQ(3, ImageDecodingStore::instance()->imageCacheEntries());
    360     EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
    361     EXPECT_EQ(0, m_decodersDestroyed);
    362 
    363     addNewData();
    364     setFrameStatus(ImageFrame::FrameComplete);
    365     scaledImage = m_generator->decodeAndScale(scaledSize());
    366     EXPECT_TRUE(scaledImage->isComplete());
    367     EXPECT_EQ(3, m_frameBufferRequestCount);
    368     ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
    369     EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries());
    370     EXPECT_EQ(5, ImageDecodingStore::instance()->imageCacheEntries());
    371     EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
    372     EXPECT_EQ(1, m_decodersDestroyed);
    373 }
    374 
    375 TEST_F(ImageFrameGeneratorTest, incompleteBitmapCopied)
    376 {
    377     setFrameStatus(ImageFrame::FramePartial);
    378 
    379     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
    380     EXPECT_FALSE(tempImage->isComplete());
    381     EXPECT_EQ(1, m_frameBufferRequestCount);
    382 
    383     ImageDecoder* tempDecoder = 0;
    384     EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder));
    385     ASSERT_TRUE(tempDecoder);
    386     EXPECT_NE(tempDecoder->frameBufferAtIndex(0)->getSkBitmap().getPixels(), tempImage->bitmap().getPixels());
    387     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    388     ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder);
    389 }
    390 
    391 TEST_F(ImageFrameGeneratorTest, resumeDecodeEmptyFrameTurnsComplete)
    392 {
    393     m_generator = ImageFrameGenerator::create(fullSize(), m_data, false, true);
    394     useMockImageDecoderFactory();
    395     setFrameStatus(ImageFrame::FrameComplete);
    396 
    397     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize(), 0);
    398     EXPECT_TRUE(tempImage->isComplete());
    399     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
    400 
    401     setFrameStatus(ImageFrame::FrameEmpty);
    402     setNextFrameStatus(ImageFrame::FrameComplete);
    403     EXPECT_FALSE(m_generator->decodeAndScale(fullSize(), 1));
    404 }
    405 
    406 TEST_F(ImageFrameGeneratorTest, frameHasAlpha)
    407 {
    408     setFrameStatus(ImageFrame::FramePartial);
    409     ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1));
    410     EXPECT_TRUE(m_generator->hasAlpha(1));
    411 
    412     ImageDecoder* tempDecoder = 0;
    413     EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder));
    414     ASSERT_TRUE(tempDecoder);
    415     static_cast<MockImageDecoder*>(tempDecoder)->setFrameHasAlpha(false);
    416     ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder);
    417 
    418     setFrameStatus(ImageFrame::FrameComplete);
    419     ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1));
    420     EXPECT_FALSE(m_generator->hasAlpha(1));
    421 }
    422 
    423 namespace {
    424 
    425 class MockAllocator : public SkBitmap::Allocator {
    426 public:
    427     // N starts from 0.
    428     MockAllocator(int failAtNthCall)
    429         : m_callCount(0)
    430         , m_failAtNthCall(failAtNthCall)
    431         , m_defaultAllocator(adoptPtr(new DiscardablePixelRefAllocator()))
    432     {
    433     }
    434 
    435     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* colorTable) OVERRIDE
    436     {
    437         if (m_callCount++ == m_failAtNthCall)
    438             return false;
    439         return m_defaultAllocator->allocPixelRef(bitmap, colorTable);
    440     }
    441 
    442     int m_callCount;
    443     int m_failAtNthCall;
    444     OwnPtr<SkBitmap::Allocator> m_defaultAllocator;
    445 };
    446 
    447 } // namespace
    448 
    449 TEST_F(ImageFrameGeneratorTest, decodingAllocatorFailure)
    450 {
    451     // Try to emulate allocation failures at different stages. For now, the
    452     // first allocation is for the bitmap in ImageFrame, the second is for the
    453     // copy of partial bitmap. The loop will still work if the number or purpose
    454     // of allocations change in the future.
    455     for (int i = 0; ; ++i) {
    456         SCOPED_TRACE(testing::Message() << "Allocation failure at call " << i);
    457         setFrameStatus(ImageFrame::FramePartial);
    458         setAllocator(adoptPtr(new MockAllocator(i)));
    459         OwnPtr<ScaledImageFragment> image = decode(0);
    460         if (i >= static_cast<MockAllocator*>(allocator())->m_callCount) {
    461             // We have tested failures of all stages. This time all allocations
    462             // were successful.
    463             EXPECT_TRUE(image);
    464             break;
    465         }
    466         EXPECT_FALSE(image);
    467     }
    468 }
    469 
    470 } // namespace WebCore
    471