@@ -34,6 +34,11 @@ using namespace mozilla::image;
3434static already_AddRefed<SourceSurface>
3535CheckDecoderState (const ImageTestCase& aTestCase, Decoder* aDecoder)
3636{
37+ // Decoder should match what we asked for in the MIME type.
38+ EXPECT_NE (aDecoder->GetType (), DecoderType::UNKNOWN );
39+ EXPECT_EQ (aDecoder->GetType (),
40+ DecoderFactory::GetDecoderType (aTestCase.mMimeType ));
41+
3742 EXPECT_TRUE (aDecoder->GetDecodeDone ());
3843 EXPECT_EQ (bool (aTestCase.mFlags & TEST_CASE_HAS_ERROR ),
3944 aDecoder->HasError ());
@@ -119,7 +124,8 @@ void WithSingleChunkDecode(const ImageTestCase& aTestCase,
119124 DecoderFlags::FIRST_FRAME_ONLY ,
120125 DefaultSurfaceFlags ());
121126 ASSERT_TRUE (decoder != nullptr );
122- RefPtr<IDecodingTask> task = new AnonymousDecodingTask (WrapNotNull (decoder));
127+ RefPtr<IDecodingTask> task =
128+ new AnonymousDecodingTask (WrapNotNull (decoder), /* aResumable */ false );
123129
124130 // Run the full decoder synchronously.
125131 task->Run ();
@@ -136,6 +142,58 @@ CheckDecoderSingleChunk(const ImageTestCase& aTestCase)
136142 });
137143}
138144
145+ template <typename Func>
146+ void WithDelayedChunkDecode (const ImageTestCase& aTestCase,
147+ const Maybe<IntSize>& aOutputSize,
148+ Func aResultChecker)
149+ {
150+ nsCOMPtr<nsIInputStream> inputStream = LoadFile (aTestCase.mPath );
151+ ASSERT_TRUE (inputStream != nullptr );
152+
153+ // Figure out how much data we have.
154+ uint64_t length;
155+ nsresult rv = inputStream->Available (&length);
156+ ASSERT_TRUE (NS_SUCCEEDED (rv));
157+
158+ // Prepare an empty SourceBuffer.
159+ auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
160+
161+ // Create a decoder.
162+ DecoderType decoderType =
163+ DecoderFactory::GetDecoderType (aTestCase.mMimeType );
164+ RefPtr<Decoder> decoder =
165+ DecoderFactory::CreateAnonymousDecoder (decoderType, sourceBuffer, aOutputSize,
166+ DecoderFlags::FIRST_FRAME_ONLY ,
167+ DefaultSurfaceFlags ());
168+ ASSERT_TRUE (decoder != nullptr );
169+ RefPtr<IDecodingTask> task =
170+ new AnonymousDecodingTask (WrapNotNull (decoder), /* aResumable */ true );
171+
172+ // Run the full decoder synchronously. It should now be waiting on
173+ // the iterator to yield some data since we haven't written anything yet.
174+ task->Run ();
175+
176+ // Writing all of the data should wake up the decoder to complete.
177+ sourceBuffer->ExpectLength (length);
178+ rv = sourceBuffer->AppendFromInputStream (inputStream, length);
179+ ASSERT_TRUE (NS_SUCCEEDED (rv));
180+ sourceBuffer->Complete (NS_OK );
181+
182+ // It would have gotten posted to the main thread to avoid mutex contention.
183+ SpinPendingEvents ();
184+
185+ // Call the lambda to verify the expected results.
186+ aResultChecker (decoder);
187+ }
188+
189+ static void
190+ CheckDecoderDelayedChunk (const ImageTestCase& aTestCase)
191+ {
192+ WithDelayedChunkDecode (aTestCase, Nothing (), [&](Decoder* aDecoder) {
193+ CheckDecoderResults (aTestCase, aDecoder);
194+ });
195+ }
196+
139197static void
140198CheckDecoderMultiChunk (const ImageTestCase& aTestCase)
141199{
@@ -157,7 +215,8 @@ CheckDecoderMultiChunk(const ImageTestCase& aTestCase)
157215 DecoderFlags::FIRST_FRAME_ONLY ,
158216 DefaultSurfaceFlags ());
159217 ASSERT_TRUE (decoder != nullptr );
160- RefPtr<IDecodingTask> task = new AnonymousDecodingTask (WrapNotNull (decoder));
218+ RefPtr<IDecodingTask> task =
219+ new AnonymousDecodingTask (WrapNotNull (decoder), /* aResumable */ false );
161220
162221 for (uint64_t read = 0 ; read < length ; ++read) {
163222 uint64_t available = 0 ;
@@ -581,6 +640,11 @@ TEST_F(ImageDecoders, PNGSingleChunk)
581640 CheckDecoderSingleChunk (GreenPNGTestCase ());
582641}
583642
643+ TEST_F (ImageDecoders, PNGDelayedChunk)
644+ {
645+ CheckDecoderDelayedChunk (GreenPNGTestCase ());
646+ }
647+
584648TEST_F (ImageDecoders, PNGMultiChunk)
585649{
586650 CheckDecoderMultiChunk (GreenPNGTestCase ());
@@ -596,6 +660,11 @@ TEST_F(ImageDecoders, GIFSingleChunk)
596660 CheckDecoderSingleChunk (GreenGIFTestCase ());
597661}
598662
663+ TEST_F (ImageDecoders, GIFDelayedChunk)
664+ {
665+ CheckDecoderDelayedChunk (GreenGIFTestCase ());
666+ }
667+
599668TEST_F (ImageDecoders, GIFMultiChunk)
600669{
601670 CheckDecoderMultiChunk (GreenGIFTestCase ());
@@ -611,6 +680,11 @@ TEST_F(ImageDecoders, JPGSingleChunk)
611680 CheckDecoderSingleChunk (GreenJPGTestCase ());
612681}
613682
683+ TEST_F (ImageDecoders, JPGDelayedChunk)
684+ {
685+ CheckDecoderDelayedChunk (GreenJPGTestCase ());
686+ }
687+
614688TEST_F (ImageDecoders, JPGMultiChunk)
615689{
616690 CheckDecoderMultiChunk (GreenJPGTestCase ());
@@ -626,6 +700,11 @@ TEST_F(ImageDecoders, BMPSingleChunk)
626700 CheckDecoderSingleChunk (GreenBMPTestCase ());
627701}
628702
703+ TEST_F (ImageDecoders, BMPDelayedChunk)
704+ {
705+ CheckDecoderDelayedChunk (GreenBMPTestCase ());
706+ }
707+
629708TEST_F (ImageDecoders, BMPMultiChunk)
630709{
631710 CheckDecoderMultiChunk (GreenBMPTestCase ());
@@ -641,6 +720,11 @@ TEST_F(ImageDecoders, ICOSingleChunk)
641720 CheckDecoderSingleChunk (GreenICOTestCase ());
642721}
643722
723+ TEST_F (ImageDecoders, ICODelayedChunk)
724+ {
725+ CheckDecoderDelayedChunk (GreenICOTestCase ());
726+ }
727+
644728TEST_F (ImageDecoders, ICOMultiChunk)
645729{
646730 CheckDecoderMultiChunk (GreenICOTestCase ());
@@ -661,6 +745,11 @@ TEST_F(ImageDecoders, IconSingleChunk)
661745 CheckDecoderSingleChunk (GreenIconTestCase ());
662746}
663747
748+ TEST_F (ImageDecoders, IconDelayedChunk)
749+ {
750+ CheckDecoderDelayedChunk (GreenIconTestCase ());
751+ }
752+
664753TEST_F (ImageDecoders, IconMultiChunk)
665754{
666755 CheckDecoderMultiChunk (GreenIconTestCase ());
@@ -676,6 +765,11 @@ TEST_F(ImageDecoders, WebPSingleChunk)
676765 CheckDecoderSingleChunk (GreenWebPTestCase ());
677766}
678767
768+ TEST_F (ImageDecoders, WebPDelayedChunk)
769+ {
770+ CheckDecoderDelayedChunk (GreenWebPTestCase ());
771+ }
772+
679773TEST_F (ImageDecoders, WebPMultiChunk)
680774{
681775 CheckDecoderMultiChunk (GreenWebPTestCase ());
0 commit comments