tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestDecoders.cpp (43020B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "gtest/gtest.h"
      6 
      7 #include "Common.h"
      8 #include "mozilla/Monitor.h"
      9 #include "AnimationSurfaceProvider.h"
     10 #include "DecodePool.h"
     11 #include "Decoder.h"
     12 #include "DecoderFactory.h"
     13 #include "decoders/nsBMPDecoder.h"
     14 #include "IDecodingTask.h"
     15 #include "ImageOps.h"
     16 #include "imgIContainer.h"
     17 #include "ImageFactory.h"
     18 #include "mozilla/ScopeExit.h"
     19 #include "mozilla/gfx/2D.h"
     20 #include "nsComponentManagerUtils.h"
     21 #include "nsCOMPtr.h"
     22 #include "nsIInputStream.h"
     23 #include "mozilla/RefPtr.h"
     24 #include "nsStreamUtils.h"
     25 #include "nsString.h"
     26 #include "nsThreadUtils.h"
     27 #include "ProgressTracker.h"
     28 #include "SourceBuffer.h"
     29 
     30 using namespace mozilla;
     31 using namespace mozilla::gfx;
     32 using namespace mozilla::image;
     33 
     34 static already_AddRefed<SourceSurface> CheckDecoderState(
     35    const ImageTestCase& aTestCase, image::Decoder* aDecoder) {
     36  // image::Decoder should match what we asked for in the MIME type.
     37  EXPECT_NE(aDecoder->GetType(), DecoderType::UNKNOWN);
     38  EXPECT_EQ(aDecoder->GetType(),
     39            DecoderFactory::GetDecoderType(aTestCase.mMimeType));
     40 
     41  EXPECT_TRUE(aDecoder->GetDecodeDone());
     42  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), aDecoder->HasError());
     43 
     44  // Verify that the decoder made the expected progress.
     45  Progress progress = aDecoder->TakeProgress();
     46  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
     47            bool(progress & FLAG_HAS_ERROR));
     48 
     49  if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
     50    return nullptr;  // That's all we can check for bad images.
     51  }
     52 
     53  EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
     54  EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
     55  EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
     56  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
     57            bool(progress & FLAG_HAS_TRANSPARENCY));
     58  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
     59            bool(progress & FLAG_IS_ANIMATED));
     60 
     61  // The decoder should get the correct size.
     62  OrientedIntSize size = aDecoder->Size();
     63  EXPECT_EQ(aTestCase.mSize.width, size.width);
     64  EXPECT_EQ(aTestCase.mSize.height, size.height);
     65 
     66  // Get the current frame, which is always the first frame of the image
     67  // because CreateAnonymousDecoder() forces a first-frame-only decode.
     68  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
     69  RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
     70 
     71  // Verify that the resulting surfaces matches our expectations.
     72  EXPECT_TRUE(surface->IsDataSourceSurface());
     73  EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX ||
     74              surface->GetFormat() == SurfaceFormat::OS_RGBA);
     75  EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());
     76 
     77  return surface.forget();
     78 }
     79 
     80 static void CheckDecoderResults(const ImageTestCase& aTestCase,
     81                                image::Decoder* aDecoder) {
     82  RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder);
     83  if (!surface) {
     84    return;
     85  }
     86 
     87  if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
     88    return;
     89  }
     90 
     91  // Check the output.
     92  EXPECT_TRUE(IsSolidColor(surface, aTestCase.Color(), aTestCase.Fuzz()));
     93 }
     94 
     95 template <typename Func>
     96 void WithBadBufferDecode(const ImageTestCase& aTestCase,
     97                         const Maybe<IntSize>& aOutputSize,
     98                         Func aResultChecker) {
     99  // Prepare a SourceBuffer with an error that will immediately move iterators
    100  // to COMPLETE.
    101  auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
    102  sourceBuffer->ExpectLength(SIZE_MAX);
    103 
    104  // Create a decoder.
    105  DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
    106  RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
    107      decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY,
    108      aTestCase.mSurfaceFlags);
    109  ASSERT_TRUE(decoder != nullptr);
    110  RefPtr<IDecodingTask> task =
    111      new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
    112 
    113  // Run the full decoder synchronously on the main thread.
    114  task->Run();
    115 
    116  // Call the lambda to verify the expected results.
    117  aResultChecker(decoder);
    118 }
    119 
    120 static void CheckDecoderBadBuffer(const ImageTestCase& aTestCase) {
    121  WithBadBufferDecode(aTestCase, Nothing(), [&](image::Decoder* aDecoder) {
    122    CheckDecoderResults(aTestCase, aDecoder);
    123  });
    124 }
    125 
    126 /**
    127 * AnonymousDecodingTask but with a monitor so we can wait for it to finish
    128 * safely.
    129 */
    130 class MonitorAnonymousDecodingTask final : public AnonymousDecodingTask {
    131 public:
    132  explicit MonitorAnonymousDecodingTask(NotNull<Decoder*> aDecoder,
    133                                        bool aResumable);
    134 
    135  void Run() override;
    136 
    137  void WaitUntilFinished();
    138 
    139 private:
    140  virtual ~MonitorAnonymousDecodingTask() = default;
    141 
    142  Monitor mMonitor MOZ_UNANNOTATED;
    143 };
    144 
    145 MonitorAnonymousDecodingTask::MonitorAnonymousDecodingTask(
    146    NotNull<Decoder*> aDecoder, bool aResumable)
    147    : AnonymousDecodingTask(aDecoder, aResumable),
    148      mMonitor("MonitorAnonymousDecodingTask") {}
    149 
    150 void MonitorAnonymousDecodingTask::Run() {
    151  MonitorAutoLock lock(mMonitor);
    152 
    153  while (true) {
    154    LexerResult result = mDecoder->Decode(WrapNotNull(this));
    155 
    156    if (result.is<TerminalState>()) {
    157      mMonitor.NotifyAll();
    158      return;  // We're done.
    159    }
    160 
    161    if (result == LexerResult(Yield::NEED_MORE_DATA)) {
    162      // We can't make any more progress right now. Let the caller decide how to
    163      // handle it.
    164      mMonitor.NotifyAll();
    165      return;
    166    }
    167 
    168    // Right now we don't do anything special for other kinds of yields, so just
    169    // keep working.
    170    MOZ_ASSERT(result.is<Yield>());
    171  }
    172 }
    173 
    174 void MonitorAnonymousDecodingTask::WaitUntilFinished() {
    175  MonitorAutoLock lock(mMonitor);
    176 
    177  while (true) {
    178    if (mDecoder->GetDecodeDone()) {
    179      return;
    180    }
    181 
    182    // Not done yet, so we'll have to wait.
    183    mMonitor.Wait();
    184  }
    185 }
    186 
    187 template <typename Func>
    188 void WithSingleChunkDecode(const ImageTestCase& aTestCase,
    189                           const Maybe<IntSize>& aOutputSize,
    190                           bool aUseDecodePool, Func aResultChecker) {
    191  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
    192  ASSERT_TRUE(inputStream != nullptr);
    193 
    194  // Figure out how much data we have.
    195  uint64_t length;
    196  nsresult rv = inputStream->Available(&length);
    197  ASSERT_NS_SUCCEEDED(rv);
    198 
    199  // Write the data into a SourceBuffer.
    200  auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
    201  sourceBuffer->ExpectLength(length);
    202  rv = sourceBuffer->AppendFromInputStream(inputStream, length);
    203  ASSERT_NS_SUCCEEDED(rv);
    204  sourceBuffer->Complete(NS_OK);
    205 
    206  // Create a decoder.
    207  DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
    208  DecoderFlags decoderFlags =
    209      DecoderFactory::GetDefaultDecoderFlagsForType(decoderType) |
    210      DecoderFlags::FIRST_FRAME_ONLY;
    211  RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
    212      decoderType, sourceBuffer, aOutputSize, decoderFlags,
    213      aTestCase.mSurfaceFlags);
    214  ASSERT_TRUE(decoder != nullptr);
    215  RefPtr<MonitorAnonymousDecodingTask> task = new MonitorAnonymousDecodingTask(
    216      WrapNotNull(decoder), /* aResumable */ false);
    217 
    218  if (aUseDecodePool) {
    219    DecodePool::Singleton()->AsyncRun(task.get());
    220 
    221    task->WaitUntilFinished();
    222  } else {  // Run the full decoder synchronously on the main thread.
    223    task->Run();
    224  }
    225 
    226  // Call the lambda to verify the expected results.
    227  aResultChecker(decoder);
    228 }
    229 
    230 static void CheckDecoderSingleChunk(const ImageTestCase& aTestCase,
    231                                    bool aUseDecodePool = false) {
    232  WithSingleChunkDecode(aTestCase, Nothing(), aUseDecodePool,
    233                        [&](image::Decoder* aDecoder) {
    234                          CheckDecoderResults(aTestCase, aDecoder);
    235                        });
    236 }
    237 
    238 template <typename Func>
    239 void WithDelayedChunkDecode(const ImageTestCase& aTestCase,
    240                            const Maybe<IntSize>& aOutputSize,
    241                            Func aResultChecker) {
    242  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
    243  ASSERT_TRUE(inputStream != nullptr);
    244 
    245  // Figure out how much data we have.
    246  uint64_t length;
    247  nsresult rv = inputStream->Available(&length);
    248  ASSERT_NS_SUCCEEDED(rv);
    249 
    250  // Prepare an empty SourceBuffer.
    251  auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
    252 
    253  // Create a decoder.
    254  DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
    255  RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
    256      decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY,
    257      aTestCase.mSurfaceFlags);
    258  ASSERT_TRUE(decoder != nullptr);
    259  RefPtr<IDecodingTask> task =
    260      new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ true);
    261 
    262  // Run the full decoder synchronously. It should now be waiting on
    263  // the iterator to yield some data since we haven't written anything yet.
    264  task->Run();
    265 
    266  // Writing all of the data should wake up the decoder to complete.
    267  sourceBuffer->ExpectLength(length);
    268  rv = sourceBuffer->AppendFromInputStream(inputStream, length);
    269  ASSERT_NS_SUCCEEDED(rv);
    270  sourceBuffer->Complete(NS_OK);
    271 
    272  // It would have gotten posted to the main thread to avoid mutex contention.
    273  SpinPendingEvents();
    274 
    275  // Call the lambda to verify the expected results.
    276  aResultChecker(decoder);
    277 }
    278 
    279 static void CheckDecoderDelayedChunk(const ImageTestCase& aTestCase) {
    280  WithDelayedChunkDecode(aTestCase, Nothing(), [&](image::Decoder* aDecoder) {
    281    CheckDecoderResults(aTestCase, aDecoder);
    282  });
    283 }
    284 
    285 static void CheckDecoderMultiChunk(const ImageTestCase& aTestCase,
    286                                   uint64_t aChunkSize = 1) {
    287  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
    288  ASSERT_TRUE(inputStream != nullptr);
    289 
    290  // Figure out how much data we have.
    291  uint64_t length;
    292  nsresult rv = inputStream->Available(&length);
    293  ASSERT_NS_SUCCEEDED(rv);
    294 
    295  // Create a SourceBuffer and a decoder.
    296  auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
    297  sourceBuffer->ExpectLength(length);
    298  DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
    299  DecoderFlags decoderFlags =
    300      DecoderFactory::GetDefaultDecoderFlagsForType(decoderType) |
    301      DecoderFlags::FIRST_FRAME_ONLY;
    302  RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
    303      decoderType, sourceBuffer, Nothing(), decoderFlags,
    304      aTestCase.mSurfaceFlags);
    305  ASSERT_TRUE(decoder != nullptr);
    306  RefPtr<IDecodingTask> task =
    307      new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ true);
    308 
    309  // Run the full decoder synchronously. It should now be waiting on
    310  // the iterator to yield some data since we haven't written anything yet.
    311  task->Run();
    312 
    313  while (length > 0) {
    314    uint64_t read = length > aChunkSize ? aChunkSize : length;
    315    length -= read;
    316 
    317    uint64_t available = 0;
    318    rv = inputStream->Available(&available);
    319    ASSERT_TRUE(available >= read);
    320    ASSERT_NS_SUCCEEDED(rv);
    321 
    322    // Writing any data should wake up the decoder to complete.
    323    rv = sourceBuffer->AppendFromInputStream(inputStream, read);
    324    ASSERT_NS_SUCCEEDED(rv);
    325 
    326    // It would have gotten posted to the main thread to avoid mutex contention.
    327    SpinPendingEvents();
    328  }
    329 
    330  sourceBuffer->Complete(NS_OK);
    331  SpinPendingEvents();
    332 
    333  CheckDecoderResults(aTestCase, decoder);
    334 }
    335 
    336 static void CheckDownscaleDuringDecode(const ImageTestCase& aTestCase) {
    337  // This function expects that |aTestCase| consists of 25 lines of green,
    338  // followed by 25 lines of red, followed by 25 lines of green, followed by 25
    339  // more lines of red. We'll downscale it from 100x100 to 20x20.
    340  IntSize outputSize(20, 20);
    341 
    342  WithSingleChunkDecode(
    343      aTestCase, Some(outputSize), /* aUseDecodePool */ false,
    344      [&](image::Decoder* aDecoder) {
    345        RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder);
    346 
    347        // There are no downscale-during-decode tests that have
    348        // TEST_CASE_HAS_ERROR set, so we expect to always get a surface here.
    349        EXPECT_TRUE(surface != nullptr);
    350 
    351        if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
    352          return;
    353        }
    354 
    355        // Check that the downscaled image is correct. Note that we skip rows
    356        // near the transitions between colors, since the downscaler does not
    357        // produce a sharp boundary at these points. Even some of the rows we
    358        // test need a small amount of fuzz; this is just the nature of Lanczos
    359        // downscaling.
    360        EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4,
    361                                      aTestCase.ChooseColor(BGRAColor::Green()),
    362                                      /* aFuzz = */ 47));
    363        EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3,
    364                                      aTestCase.ChooseColor(BGRAColor::Red()),
    365                                      /* aFuzz = */ 27));
    366        EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(),
    367                                      /* aFuzz = */ 47));
    368        EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4,
    369                                      aTestCase.ChooseColor(BGRAColor::Red()),
    370                                      /* aFuzz = */ 27));
    371      });
    372 }
    373 
    374 static void CheckAnimationDecoderResults(const ImageTestCase& aTestCase,
    375                                         AnimationSurfaceProvider* aProvider,
    376                                         image::Decoder* aDecoder) {
    377  EXPECT_TRUE(aDecoder->GetDecodeDone());
    378  EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), aDecoder->HasError());
    379 
    380  if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
    381    return;  // That's all we can check for bad images.
    382  }
    383 
    384  // The decoder should get the correct size.
    385  OrientedIntSize size = aDecoder->Size();
    386  EXPECT_EQ(aTestCase.mSize.width, size.width);
    387  EXPECT_EQ(aTestCase.mSize.height, size.height);
    388 
    389  if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
    390    return;
    391  }
    392 
    393  // Check the output.
    394  AutoTArray<BGRAColor, 2> framePixels;
    395  framePixels.AppendElement(aTestCase.ChooseColor(BGRAColor::Green()));
    396  framePixels.AppendElement(
    397      aTestCase.ChooseColor(BGRAColor(0x7F, 0x7F, 0x7F, 0xFF)));
    398 
    399  DrawableSurface drawableSurface(WrapNotNull(aProvider));
    400  for (size_t i = 0; i < framePixels.Length(); ++i) {
    401    nsresult rv = drawableSurface.Seek(i);
    402    EXPECT_NS_SUCCEEDED(rv);
    403 
    404    // Check the first frame, all green.
    405    RawAccessFrameRef rawFrame = drawableSurface->RawAccessRef();
    406    RefPtr<SourceSurface> surface = rawFrame->GetSourceSurface();
    407 
    408    // Verify that the resulting surfaces matches our expectations.
    409    EXPECT_TRUE(surface->IsDataSourceSurface());
    410    EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX ||
    411                surface->GetFormat() == SurfaceFormat::OS_RGBA);
    412    EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());
    413    EXPECT_TRUE(IsSolidColor(surface, framePixels[i], aTestCase.Fuzz()));
    414  }
    415 
    416  // Should be no more frames.
    417  nsresult rv = drawableSurface.Seek(framePixels.Length());
    418  EXPECT_NS_FAILED(rv);
    419 }
    420 
    421 template <typename Func>
    422 static void WithSingleChunkAnimationDecode(const ImageTestCase& aTestCase,
    423                                           Func aResultChecker) {
    424  // Create an image.
    425  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
    426      nsDependentCString(aTestCase.mMimeType));
    427  ASSERT_TRUE(!image->HasError());
    428 
    429  NotNull<RefPtr<RasterImage>> rasterImage =
    430      WrapNotNull(static_cast<RasterImage*>(image.get()));
    431 
    432  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
    433  ASSERT_TRUE(inputStream != nullptr);
    434 
    435  // Figure out how much data we have.
    436  uint64_t length;
    437  nsresult rv = inputStream->Available(&length);
    438  ASSERT_NS_SUCCEEDED(rv);
    439 
    440  // Write the data into a SourceBuffer.
    441  NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
    442  sourceBuffer->ExpectLength(length);
    443  rv = sourceBuffer->AppendFromInputStream(inputStream, length);
    444  ASSERT_NS_SUCCEEDED(rv);
    445  sourceBuffer->Complete(NS_OK);
    446 
    447  // Create a metadata decoder first, because otherwise RasterImage will get
    448  // unhappy about finding out the image is animated during a full decode.
    449  DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
    450  DecoderFlags decoderFlags =
    451      DecoderFactory::GetDefaultDecoderFlagsForType(decoderType);
    452  RefPtr<IDecodingTask> task = DecoderFactory::CreateMetadataDecoder(
    453      decoderType, rasterImage, decoderFlags, sourceBuffer);
    454  ASSERT_TRUE(task != nullptr);
    455 
    456  // Run the metadata decoder synchronously.
    457  task->Run();
    458 
    459  // Create a decoder.
    460  SurfaceFlags surfaceFlags = aTestCase.mSurfaceFlags;
    461  RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
    462      decoderType, sourceBuffer, Nothing(), decoderFlags, surfaceFlags);
    463  ASSERT_TRUE(decoder != nullptr);
    464 
    465  // Create an AnimationSurfaceProvider which will manage the decoding process
    466  // and make this decoder's output available in the surface cache.
    467  SurfaceKey surfaceKey = RasterSurfaceKey(aTestCase.mOutputSize, surfaceFlags,
    468                                           PlaybackType::eAnimated);
    469  RefPtr<AnimationSurfaceProvider> provider = new AnimationSurfaceProvider(
    470      rasterImage, surfaceKey, WrapNotNull(decoder),
    471      /* aCurrentFrame */ 0);
    472 
    473  // Run the full decoder synchronously.
    474  provider->Run();
    475 
    476  // Call the lambda to verify the expected results.
    477  aResultChecker(provider, decoder);
    478 }
    479 
    480 static void CheckAnimationDecoderSingleChunk(const ImageTestCase& aTestCase) {
    481  WithSingleChunkAnimationDecode(
    482      aTestCase,
    483      [&](AnimationSurfaceProvider* aProvider, image::Decoder* aDecoder) {
    484        CheckAnimationDecoderResults(aTestCase, aProvider, aDecoder);
    485      });
    486 }
    487 
    488 static void CheckDecoderFrameFirst(const ImageTestCase& aTestCase) {
    489  // Verify that we can decode this test case and retrieve the first frame using
    490  // imgIContainer::FRAME_FIRST. This ensures that we correctly trigger a
    491  // single-frame decode rather than an animated decode when
    492  // imgIContainer::FRAME_FIRST is requested.
    493 
    494  // Create an image.
    495  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
    496      nsDependentCString(aTestCase.mMimeType));
    497  ASSERT_TRUE(!image->HasError());
    498 
    499  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
    500  ASSERT_TRUE(inputStream);
    501 
    502  // Figure out how much data we have.
    503  uint64_t length;
    504  nsresult rv = inputStream->Available(&length);
    505  ASSERT_NS_SUCCEEDED(rv);
    506 
    507  // Write the data into the image.
    508  rv = image->OnImageDataAvailable(nullptr, inputStream, 0,
    509                                   static_cast<uint32_t>(length));
    510  ASSERT_NS_SUCCEEDED(rv);
    511 
    512  // Let the image know we've sent all the data.
    513  rv = image->OnImageDataComplete(nullptr, NS_OK, true);
    514  ASSERT_NS_SUCCEEDED(rv);
    515 
    516  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
    517  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
    518 
    519  // Lock the image so its surfaces don't disappear during the test.
    520  image->LockImage();
    521 
    522  auto unlock = mozilla::MakeScopeExit([&] { image->UnlockImage(); });
    523 
    524  // Use GetFrame() to force a sync decode of the image, specifying FRAME_FIRST
    525  // to ensure that we don't get an animated decode.
    526  RefPtr<SourceSurface> surface = image->GetFrame(
    527      imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE);
    528 
    529  // Ensure that the image's metadata meets our expectations.
    530  IntSize imageSize(0, 0);
    531  rv = image->GetWidth(&imageSize.width);
    532  EXPECT_NS_SUCCEEDED(rv);
    533  rv = image->GetHeight(&imageSize.height);
    534  EXPECT_NS_SUCCEEDED(rv);
    535 
    536  EXPECT_EQ(aTestCase.mSize.width, imageSize.width);
    537  EXPECT_EQ(aTestCase.mSize.height, imageSize.height);
    538 
    539  Progress imageProgress = tracker->GetProgress();
    540 
    541  EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
    542  EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
    543 
    544  // Ensure that we decoded the static version of the image.
    545  {
    546    LookupResult result = SurfaceCache::Lookup(
    547        ImageKey(image.get()),
    548        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    549                         PlaybackType::eStatic),
    550        /* aMarkUsed = */ false);
    551    ASSERT_EQ(MatchType::EXACT, result.Type());
    552    EXPECT_TRUE(bool(result.Surface()));
    553  }
    554 
    555  // Ensure that we didn't decode the animated version of the image.
    556  {
    557    LookupResult result = SurfaceCache::Lookup(
    558        ImageKey(image.get()),
    559        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    560                         PlaybackType::eAnimated),
    561        /* aMarkUsed = */ false);
    562    ASSERT_EQ(MatchType::NOT_FOUND, result.Type());
    563  }
    564 
    565  // Use GetFrame() to force a sync decode of the image, this time specifying
    566  // FRAME_CURRENT to ensure that we get an animated decode.
    567  RefPtr<SourceSurface> animatedSurface = image->GetFrame(
    568      imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
    569 
    570  // Ensure that we decoded both frames of the animated version of the image.
    571  {
    572    LookupResult result = SurfaceCache::Lookup(
    573        ImageKey(image.get()),
    574        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    575                         PlaybackType::eAnimated),
    576        /* aMarkUsed = */ true);
    577    ASSERT_EQ(MatchType::EXACT, result.Type());
    578 
    579    EXPECT_NS_SUCCEEDED(result.Surface().Seek(0));
    580    EXPECT_TRUE(bool(result.Surface()));
    581 
    582    RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
    583    EXPECT_TRUE(bool(partialFrame));
    584  }
    585 
    586  // Ensure that the static version is still around.
    587  {
    588    LookupResult result = SurfaceCache::Lookup(
    589        ImageKey(image.get()),
    590        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    591                         PlaybackType::eStatic),
    592        /* aMarkUsed = */ true);
    593    ASSERT_EQ(MatchType::EXACT, result.Type());
    594    EXPECT_TRUE(bool(result.Surface()));
    595  }
    596 }
    597 
    598 static void CheckDecoderFrameCurrent(const ImageTestCase& aTestCase) {
    599  // Verify that we can decode this test case and retrieve the entire sequence
    600  // of frames using imgIContainer::FRAME_CURRENT. This ensures that we
    601  // correctly trigger an animated decode rather than a single-frame decode when
    602  // imgIContainer::FRAME_CURRENT is requested.
    603 
    604  // Create an image.
    605  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
    606      nsDependentCString(aTestCase.mMimeType));
    607  ASSERT_TRUE(!image->HasError());
    608 
    609  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
    610  ASSERT_TRUE(inputStream);
    611 
    612  // Figure out how much data we have.
    613  uint64_t length;
    614  nsresult rv = inputStream->Available(&length);
    615  ASSERT_NS_SUCCEEDED(rv);
    616 
    617  // Write the data into the image.
    618  rv = image->OnImageDataAvailable(nullptr, inputStream, 0,
    619                                   static_cast<uint32_t>(length));
    620  ASSERT_NS_SUCCEEDED(rv);
    621 
    622  // Let the image know we've sent all the data.
    623  rv = image->OnImageDataComplete(nullptr, NS_OK, true);
    624  ASSERT_NS_SUCCEEDED(rv);
    625 
    626  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
    627  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
    628 
    629  // Lock the image so its surfaces don't disappear during the test.
    630  image->LockImage();
    631 
    632  // Use GetFrame() to force a sync decode of the image, specifying
    633  // FRAME_CURRENT to ensure we get an animated decode.
    634  RefPtr<SourceSurface> surface = image->GetFrame(
    635      imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
    636 
    637  // Ensure that the image's metadata meets our expectations.
    638  IntSize imageSize(0, 0);
    639  rv = image->GetWidth(&imageSize.width);
    640  EXPECT_NS_SUCCEEDED(rv);
    641  rv = image->GetHeight(&imageSize.height);
    642  EXPECT_NS_SUCCEEDED(rv);
    643 
    644  EXPECT_EQ(aTestCase.mSize.width, imageSize.width);
    645  EXPECT_EQ(aTestCase.mSize.height, imageSize.height);
    646 
    647  Progress imageProgress = tracker->GetProgress();
    648 
    649  EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
    650  EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
    651 
    652  // Ensure that we decoded both frames of the animated version of the image.
    653  {
    654    LookupResult result = SurfaceCache::Lookup(
    655        ImageKey(image.get()),
    656        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    657                         PlaybackType::eAnimated),
    658        /* aMarkUsed = */ true);
    659    ASSERT_EQ(MatchType::EXACT, result.Type());
    660 
    661    EXPECT_NS_SUCCEEDED(result.Surface().Seek(0));
    662    EXPECT_TRUE(bool(result.Surface()));
    663 
    664    RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
    665    EXPECT_TRUE(bool(partialFrame));
    666  }
    667 
    668  // Ensure that we didn't decode the static version of the image.
    669  {
    670    LookupResult result = SurfaceCache::Lookup(
    671        ImageKey(image.get()),
    672        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    673                         PlaybackType::eStatic),
    674        /* aMarkUsed = */ false);
    675    ASSERT_EQ(MatchType::NOT_FOUND, result.Type());
    676  }
    677 
    678  // Use GetFrame() to force a sync decode of the image, this time specifying
    679  // FRAME_FIRST to ensure that we get a single-frame decode.
    680  RefPtr<SourceSurface> animatedSurface = image->GetFrame(
    681      imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE);
    682 
    683  // Ensure that we decoded the static version of the image.
    684  {
    685    LookupResult result = SurfaceCache::Lookup(
    686        ImageKey(image.get()),
    687        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    688                         PlaybackType::eStatic),
    689        /* aMarkUsed = */ true);
    690    ASSERT_EQ(MatchType::EXACT, result.Type());
    691    EXPECT_TRUE(bool(result.Surface()));
    692  }
    693 
    694  // Ensure that both frames of the animated version are still around.
    695  {
    696    LookupResult result = SurfaceCache::Lookup(
    697        ImageKey(image.get()),
    698        RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
    699                         PlaybackType::eAnimated),
    700        /* aMarkUsed = */ true);
    701    ASSERT_EQ(MatchType::EXACT, result.Type());
    702 
    703    EXPECT_NS_SUCCEEDED(result.Surface().Seek(0));
    704    EXPECT_TRUE(bool(result.Surface()));
    705 
    706    RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
    707    EXPECT_TRUE(bool(partialFrame));
    708  }
    709 }
    710 
    711 class ImageDecoders : public ::testing::Test {
    712 protected:
    713  AutoInitializeImageLib mInit;
    714 };
    715 
    716 #define IMAGE_GTEST_DECODER_BASE_F(test_prefix)                              \
    717  TEST_F(ImageDecoders, test_prefix##SingleChunk) {                          \
    718    CheckDecoderSingleChunk(Green##test_prefix##TestCase());                 \
    719  }                                                                          \
    720                                                                             \
    721  TEST_F(ImageDecoders, test_prefix##DelayedChunk) {                         \
    722    CheckDecoderDelayedChunk(Green##test_prefix##TestCase());                \
    723  }                                                                          \
    724                                                                             \
    725  TEST_F(ImageDecoders, test_prefix##MultiChunk) {                           \
    726    CheckDecoderMultiChunk(Green##test_prefix##TestCase());                  \
    727  }                                                                          \
    728                                                                             \
    729  TEST_F(ImageDecoders, test_prefix##DownscaleDuringDecode) {                \
    730    CheckDownscaleDuringDecode(Downscaled##test_prefix##TestCase());         \
    731  }                                                                          \
    732                                                                             \
    733  TEST_F(ImageDecoders, test_prefix##ForceSRGB) {                            \
    734    CheckDecoderSingleChunk(Green##test_prefix##TestCase().WithSurfaceFlags( \
    735        SurfaceFlags::TO_SRGB_COLORSPACE));                                  \
    736  }                                                                          \
    737                                                                             \
    738  TEST_F(ImageDecoders, test_prefix##BadBuffer) {                            \
    739    CheckDecoderBadBuffer(Green##test_prefix##TestCase().WithFlags(          \
    740        TEST_CASE_HAS_ERROR | TEST_CASE_IGNORE_OUTPUT));                     \
    741  }
    742 
    743 IMAGE_GTEST_DECODER_BASE_F(PNG)
    744 IMAGE_GTEST_DECODER_BASE_F(GIF)
    745 IMAGE_GTEST_DECODER_BASE_F(JPG)
    746 IMAGE_GTEST_DECODER_BASE_F(BMP)
    747 IMAGE_GTEST_DECODER_BASE_F(ICO)
    748 IMAGE_GTEST_DECODER_BASE_F(Icon)
    749 IMAGE_GTEST_DECODER_BASE_F(WebP)
    750 #ifdef MOZ_JXL
    751 IMAGE_GTEST_DECODER_BASE_F(JXL)
    752 #endif
    753 
    754 TEST_F(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode) {
    755  CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase());
    756 }
    757 
    758 TEST_F(ImageDecoders, WebPLargeMultiChunk) {
    759  CheckDecoderMultiChunk(LargeWebPTestCase(), /* aChunkSize */ 64);
    760 }
    761 
    762 TEST_F(ImageDecoders, WebPIccSrgbMultiChunk) {
    763  CheckDecoderMultiChunk(GreenWebPIccSrgbTestCase());
    764 }
    765 
    766 TEST_F(ImageDecoders, WebPTransparentSingleChunk) {
    767  CheckDecoderSingleChunk(TransparentWebPTestCase());
    768 }
    769 
    770 TEST_F(ImageDecoders, WebPTransparentNoAlphaHeaderSingleChunk) {
    771  CheckDecoderSingleChunk(TransparentNoAlphaHeaderWebPTestCase());
    772 }
    773 
    774 TEST_F(ImageDecoders, AVIFSingleChunk) {
    775  CheckDecoderSingleChunk(GreenAVIFTestCase());
    776 }
    777 
    778 TEST_F(ImageDecoders, AVIFSingleChunkNonzeroReserved) {
    779  CheckDecoderSingleChunk(NonzeroReservedAVIFTestCase());
    780 }
    781 
    782 TEST_F(ImageDecoders, AVIFSingleChunkMultipleColr) {
    783  CheckDecoderSingleChunk(MultipleColrAVIFTestCase());
    784 }
    785 
    786 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit420) {
    787  CheckDecoderSingleChunk(Transparent10bit420AVIFTestCase());
    788 }
    789 
    790 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit422) {
    791  CheckDecoderSingleChunk(Transparent10bit422AVIFTestCase());
    792 }
    793 
    794 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit444) {
    795  CheckDecoderSingleChunk(Transparent10bit444AVIFTestCase());
    796 }
    797 
    798 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit420) {
    799  CheckDecoderSingleChunk(Transparent12bit420AVIFTestCase());
    800 }
    801 
    802 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit422) {
    803  CheckDecoderSingleChunk(Transparent12bit422AVIFTestCase());
    804 }
    805 
    806 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit444) {
    807  CheckDecoderSingleChunk(Transparent12bit444AVIFTestCase());
    808 }
    809 
    810 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit420) {
    811  CheckDecoderSingleChunk(Transparent8bit420AVIFTestCase());
    812 }
    813 
    814 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit422) {
    815  CheckDecoderSingleChunk(Transparent8bit422AVIFTestCase());
    816 }
    817 
    818 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit444) {
    819  CheckDecoderSingleChunk(Transparent8bit444AVIFTestCase());
    820 }
    821 
    822 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT601) {
    823  CheckDecoderSingleChunk(Gray8bitLimitedRangeBT601AVIFTestCase());
    824 }
    825 
    826 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT709) {
    827  CheckDecoderSingleChunk(Gray8bitLimitedRangeBT709AVIFTestCase());
    828 }
    829 
    830 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT2020) {
    831  CheckDecoderSingleChunk(Gray8bitLimitedRangeBT2020AVIFTestCase());
    832 }
    833 
    834 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT601) {
    835  CheckDecoderSingleChunk(Gray8bitFullRangeBT601AVIFTestCase());
    836 }
    837 
    838 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT709) {
    839  CheckDecoderSingleChunk(Gray8bitFullRangeBT709AVIFTestCase());
    840 }
    841 
    842 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT2020) {
    843  CheckDecoderSingleChunk(Gray8bitFullRangeBT2020AVIFTestCase());
    844 }
    845 
    846 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT601) {
    847  CheckDecoderSingleChunk(Gray10bitLimitedRangeBT601AVIFTestCase());
    848 }
    849 
    850 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT709) {
    851  CheckDecoderSingleChunk(Gray10bitLimitedRangeBT709AVIFTestCase());
    852 }
    853 
    854 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT2020) {
    855  CheckDecoderSingleChunk(Gray10bitLimitedRangeBT2020AVIFTestCase());
    856 }
    857 
    858 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT601) {
    859  CheckDecoderSingleChunk(Gray10bitFullRangeBT601AVIFTestCase());
    860 }
    861 
    862 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT709) {
    863  CheckDecoderSingleChunk(Gray10bitFullRangeBT709AVIFTestCase());
    864 }
    865 
    866 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT2020) {
    867  CheckDecoderSingleChunk(Gray10bitFullRangeBT2020AVIFTestCase());
    868 }
    869 
    870 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT601) {
    871  CheckDecoderSingleChunk(Gray12bitLimitedRangeBT601AVIFTestCase());
    872 }
    873 
    874 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT709) {
    875  CheckDecoderSingleChunk(Gray12bitLimitedRangeBT709AVIFTestCase());
    876 }
    877 
    878 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT2020) {
    879  CheckDecoderSingleChunk(Gray12bitLimitedRangeBT2020AVIFTestCase());
    880 }
    881 
    882 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT601) {
    883  CheckDecoderSingleChunk(Gray12bitFullRangeBT601AVIFTestCase());
    884 }
    885 
    886 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT709) {
    887  CheckDecoderSingleChunk(Gray12bitFullRangeBT709AVIFTestCase());
    888 }
    889 
    890 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT2020) {
    891  CheckDecoderSingleChunk(Gray12bitFullRangeBT2020AVIFTestCase());
    892 }
    893 
    894 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeGrayscale) {
    895  CheckDecoderSingleChunk(Gray8bitLimitedRangeGrayscaleAVIFTestCase());
    896 }
    897 
    898 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeGrayscale) {
    899  CheckDecoderSingleChunk(Gray8bitFullRangeGrayscaleAVIFTestCase());
    900 }
    901 
    902 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeGrayscale) {
    903  CheckDecoderSingleChunk(Gray10bitLimitedRangeGrayscaleAVIFTestCase());
    904 }
    905 
    906 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeGrayscale) {
    907  CheckDecoderSingleChunk(Gray10bitFullRangeGrayscaleAVIFTestCase());
    908 }
    909 
    910 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeGrayscale) {
    911  CheckDecoderSingleChunk(Gray12bitLimitedRangeGrayscaleAVIFTestCase());
    912 }
    913 
    914 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeGrayscale) {
    915  CheckDecoderSingleChunk(Gray12bitFullRangeGrayscaleAVIFTestCase());
    916 }
    917 
    918 TEST_F(ImageDecoders, AVIFMultiLayerSingleChunk) {
    919  CheckDecoderSingleChunk(MultiLayerAVIFTestCase());
    920 }
    921 
    922 // This test must use the decode pool in order to check for regressions
    923 // of crashing the dav1d decoder when the ImgDecoder threads have a standard-
    924 // sized stack.
    925 TEST_F(ImageDecoders, AVIFStackCheck) {
    926  CheckDecoderSingleChunk(StackCheckAVIFTestCase(), /* aUseDecodePool */ true);
    927 }
    928 
    929 TEST_F(ImageDecoders, AVIFDelayedChunk) {
    930  CheckDecoderDelayedChunk(GreenAVIFTestCase());
    931 }
    932 
    933 TEST_F(ImageDecoders, AVIFMultiChunk) {
    934  CheckDecoderMultiChunk(GreenAVIFTestCase());
    935 }
    936 
    937 TEST_F(ImageDecoders, AVIFLargeMultiChunk) {
    938  CheckDecoderMultiChunk(LargeAVIFTestCase(), /* aChunkSize */ 64);
    939 }
    940 
    941 TEST_F(ImageDecoders, AVIFDownscaleDuringDecode) {
    942  CheckDownscaleDuringDecode(DownscaledAVIFTestCase());
    943 }
    944 
    945 #ifdef MOZ_JXL
    946 TEST_F(ImageDecoders, JXLLargeMultiChunk) {
    947  CheckDecoderMultiChunk(LargeJXLTestCase(), /* aChunkSize */ 64);
    948 }
    949 #endif
    950 
    951 TEST_F(ImageDecoders, AnimatedGIFSingleChunk) {
    952  CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
    953 }
    954 
    955 TEST_F(ImageDecoders, AnimatedGIFMultiChunk) {
    956  CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase());
    957 }
    958 
    959 TEST_F(ImageDecoders, AnimatedGIFWithBlendedFrames) {
    960  CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
    961 }
    962 
    963 TEST_F(ImageDecoders, AnimatedPNGSingleChunk) {
    964  CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase());
    965 }
    966 
    967 TEST_F(ImageDecoders, AnimatedPNGMultiChunk) {
    968  CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase());
    969 }
    970 
    971 TEST_F(ImageDecoders, AnimatedPNGWithBlendedFrames) {
    972  CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase());
    973 }
    974 
    975 TEST_F(ImageDecoders, AnimatedWebPSingleChunk) {
    976  CheckDecoderSingleChunk(GreenFirstFrameAnimatedWebPTestCase());
    977 }
    978 
    979 TEST_F(ImageDecoders, AnimatedWebPMultiChunk) {
    980  CheckDecoderMultiChunk(GreenFirstFrameAnimatedWebPTestCase());
    981 }
    982 
    983 TEST_F(ImageDecoders, AnimatedWebPWithBlendedFrames) {
    984  CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedWebPTestCase());
    985 }
    986 
    987 TEST_F(ImageDecoders, AnimatedAVIFSingleChunk) {
    988  CheckDecoderSingleChunk(GreenFirstFrameAnimatedAVIFTestCase());
    989 }
    990 
    991 TEST_F(ImageDecoders, AnimatedAVIFMultiChunk) {
    992  CheckDecoderMultiChunk(GreenFirstFrameAnimatedAVIFTestCase());
    993 }
    994 
    995 TEST_F(ImageDecoders, AnimatedAVIFWithBlendedFrames) {
    996  CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedAVIFTestCase());
    997 }
    998 
    999 TEST_F(ImageDecoders, CorruptSingleChunk) {
   1000  CheckDecoderSingleChunk(CorruptTestCase());
   1001 }
   1002 
   1003 TEST_F(ImageDecoders, CorruptMultiChunk) {
   1004  CheckDecoderMultiChunk(CorruptTestCase());
   1005 }
   1006 
   1007 TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderSingleChunk) {
   1008  CheckDecoderSingleChunk(CorruptBMPWithTruncatedHeader());
   1009 }
   1010 
   1011 TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderMultiChunk) {
   1012  CheckDecoderMultiChunk(CorruptBMPWithTruncatedHeader());
   1013 }
   1014 
   1015 TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthSingleChunk) {
   1016  CheckDecoderSingleChunk(CorruptICOWithBadBMPWidthTestCase());
   1017 }
   1018 
   1019 TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthMultiChunk) {
   1020  CheckDecoderMultiChunk(CorruptICOWithBadBMPWidthTestCase());
   1021 }
   1022 
   1023 TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightSingleChunk) {
   1024  CheckDecoderSingleChunk(CorruptICOWithBadBMPHeightTestCase());
   1025 }
   1026 
   1027 TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk) {
   1028  CheckDecoderMultiChunk(CorruptICOWithBadBMPHeightTestCase());
   1029 }
   1030 
   1031 TEST_F(ImageDecoders, CorruptICOWithBadBppSingleChunk) {
   1032  CheckDecoderSingleChunk(CorruptICOWithBadBppTestCase());
   1033 }
   1034 
   1035 // Running this test under emulation for Android 7 on x86_64 seems to result
   1036 // in the large allocation succeeding, but leaving so little memory left the
   1037 // system falls over and it kills the test run, so we skip it instead.
   1038 // See bug 1655846 for more details.
   1039 #ifndef ANDROID
   1040 TEST_F(ImageDecoders, CorruptAVIFSingleChunk) {
   1041  CheckDecoderSingleChunk(CorruptAVIFTestCase());
   1042 }
   1043 #endif
   1044 
   1045 TEST_F(ImageDecoders, AnimatedGIFWithFRAME_FIRST) {
   1046  CheckDecoderFrameFirst(GreenFirstFrameAnimatedGIFTestCase());
   1047 }
   1048 
   1049 TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT) {
   1050  CheckDecoderFrameCurrent(GreenFirstFrameAnimatedGIFTestCase());
   1051 }
   1052 
   1053 TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) {
   1054  ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase();
   1055 
   1056  // Verify that we can decode this test case and get two frames, even though
   1057  // there are extra image sub blocks between the first and second frame. The
   1058  // extra data shouldn't confuse the decoder or cause the decode to fail.
   1059 
   1060  // Create an image.
   1061  RefPtr<Image> image = TestCaseToDecodedImage(testCase);
   1062 
   1063  // Ensure that the image's metadata meets our expectations.
   1064  IntSize imageSize(0, 0);
   1065  nsresult rv = image->GetWidth(&imageSize.width);
   1066  EXPECT_NS_SUCCEEDED(rv);
   1067  rv = image->GetHeight(&imageSize.height);
   1068  EXPECT_NS_SUCCEEDED(rv);
   1069 
   1070  EXPECT_EQ(testCase.mSize.width, imageSize.width);
   1071  EXPECT_EQ(testCase.mSize.height, imageSize.height);
   1072 
   1073  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
   1074  Progress imageProgress = tracker->GetProgress();
   1075 
   1076  EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
   1077  EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
   1078 
   1079  // Ensure that we decoded both frames of the image.
   1080  LookupResult result =
   1081      SurfaceCache::Lookup(ImageKey(image.get()),
   1082                           RasterSurfaceKey(imageSize, testCase.mSurfaceFlags,
   1083                                            PlaybackType::eAnimated),
   1084                           /* aMarkUsed = */ true);
   1085  ASSERT_EQ(MatchType::EXACT, result.Type());
   1086 
   1087  EXPECT_NS_SUCCEEDED(result.Surface().Seek(0));
   1088  EXPECT_TRUE(bool(result.Surface()));
   1089 
   1090  RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
   1091  EXPECT_TRUE(bool(partialFrame));
   1092 }
   1093 
   1094 TEST_F(ImageDecoders, AnimatedWebPWithFRAME_FIRST) {
   1095  CheckDecoderFrameFirst(GreenFirstFrameAnimatedWebPTestCase());
   1096 }
   1097 
   1098 TEST_F(ImageDecoders, AnimatedWebPWithFRAME_CURRENT) {
   1099  CheckDecoderFrameCurrent(GreenFirstFrameAnimatedWebPTestCase());
   1100 }
   1101 
   1102 TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk) {
   1103  CheckDecoderSingleChunk(TruncatedSmallGIFTestCase());
   1104 }
   1105 
   1106 TEST_F(ImageDecoders, LargeICOWithBMPSingleChunk) {
   1107  CheckDecoderSingleChunk(LargeICOWithBMPTestCase());
   1108 }
   1109 
   1110 TEST_F(ImageDecoders, LargeICOWithBMPMultiChunk) {
   1111  CheckDecoderMultiChunk(LargeICOWithBMPTestCase(), /* aChunkSize */ 64);
   1112 }
   1113 
   1114 TEST_F(ImageDecoders, LargeICOWithPNGSingleChunk) {
   1115  CheckDecoderSingleChunk(LargeICOWithPNGTestCase());
   1116 }
   1117 
   1118 TEST_F(ImageDecoders, LargeICOWithPNGMultiChunk) {
   1119  CheckDecoderMultiChunk(LargeICOWithPNGTestCase());
   1120 }
   1121 
   1122 TEST_F(ImageDecoders, MultipleSizesICOSingleChunk) {
   1123  ImageTestCase testCase = GreenMultipleSizesICOTestCase();
   1124 
   1125  // Create an image.
   1126  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
   1127      nsDependentCString(testCase.mMimeType));
   1128  ASSERT_TRUE(!image->HasError());
   1129 
   1130  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
   1131  ASSERT_TRUE(inputStream);
   1132 
   1133  // Figure out how much data we have.
   1134  uint64_t length;
   1135  nsresult rv = inputStream->Available(&length);
   1136  ASSERT_NS_SUCCEEDED(rv);
   1137 
   1138  // Write the data into the image.
   1139  rv = image->OnImageDataAvailable(nullptr, inputStream, 0,
   1140                                   static_cast<uint32_t>(length));
   1141  ASSERT_NS_SUCCEEDED(rv);
   1142 
   1143  // Let the image know we've sent all the data.
   1144  rv = image->OnImageDataComplete(nullptr, NS_OK, true);
   1145  ASSERT_NS_SUCCEEDED(rv);
   1146 
   1147  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
   1148  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
   1149 
   1150  // Use GetFrame() to force a sync decode of the image.
   1151  RefPtr<SourceSurface> surface = image->GetFrame(
   1152      imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
   1153 
   1154  // Ensure that the image's metadata meets our expectations.
   1155  IntSize imageSize(0, 0);
   1156  rv = image->GetWidth(&imageSize.width);
   1157  EXPECT_NS_SUCCEEDED(rv);
   1158  rv = image->GetHeight(&imageSize.height);
   1159  EXPECT_NS_SUCCEEDED(rv);
   1160 
   1161  EXPECT_EQ(testCase.mSize.width, imageSize.width);
   1162  EXPECT_EQ(testCase.mSize.height, imageSize.height);
   1163 
   1164  nsTArray<IntSize> nativeSizes;
   1165  rv = image->GetNativeSizes(nativeSizes);
   1166  EXPECT_NS_SUCCEEDED(rv);
   1167  ASSERT_EQ(6u, nativeSizes.Length());
   1168 
   1169  IntSize expectedSizes[] = {IntSize(16, 16),   IntSize(32, 32),
   1170                             IntSize(64, 64),   IntSize(128, 128),
   1171                             IntSize(256, 256), IntSize(256, 128)};
   1172 
   1173  for (int i = 0; i < 6; ++i) {
   1174    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
   1175  }
   1176 
   1177  RefPtr<Image> image90 =
   1178      ImageOps::Orient(image, Orientation(Angle::D90, Flip::Unflipped));
   1179  rv = image90->GetNativeSizes(nativeSizes);
   1180  EXPECT_NS_SUCCEEDED(rv);
   1181  ASSERT_EQ(6u, nativeSizes.Length());
   1182 
   1183  for (int i = 0; i < 5; ++i) {
   1184    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
   1185  }
   1186  EXPECT_EQ(IntSize(128, 256), nativeSizes[5]);
   1187 
   1188  RefPtr<Image> image180 =
   1189      ImageOps::Orient(image, Orientation(Angle::D180, Flip::Unflipped));
   1190  rv = image180->GetNativeSizes(nativeSizes);
   1191  EXPECT_NS_SUCCEEDED(rv);
   1192  ASSERT_EQ(6u, nativeSizes.Length());
   1193 
   1194  for (int i = 0; i < 6; ++i) {
   1195    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
   1196  }
   1197 }
   1198 
   1199 TEST_F(ImageDecoders, ExifResolutionEven) {
   1200  RefPtr<Image> image = TestCaseToDecodedImage(ExifResolutionTestCase());
   1201  EXPECT_EQ(image->GetResolution(), Resolution(2.0, 2.0));
   1202 }