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