Add a test to imitate GIFImageDecoderTest.parseAndDecodeByteByByte

With skia_use_wuffs=true, calling getFrameCount after the partial
decode results in the full decode failing.

Bug: skia:8235
Change-Id: I9ac5496e3fecf309f1e303a8d3e8725a6d00731b
Reviewed-on: https://skia-review.googlesource.com/c/176590
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Nigel Tao <nigeltao@google.com>
diff --git a/tests/CodecPartialTest.cpp b/tests/CodecPartialTest.cpp
index e07432a..84bc03e 100644
--- a/tests/CodecPartialTest.cpp
+++ b/tests/CodecPartialTest.cpp
@@ -58,13 +58,8 @@
     return true;
 }
 
-static void test_partial(skiatest::Reporter* r, const char* name, size_t minBytes = 0) {
-    sk_sp<SkData> file = GetResourceAsData(name);
-    if (!file) {
-        SkDebugf("missing resource %s\n", name);
-        return;
-    }
-
+static void test_partial(skiatest::Reporter* r, const char* name, const sk_sp<SkData>& file,
+                         size_t minBytes, size_t increment) {
     SkBitmap truth;
     if (!create_truth(file, &truth)) {
         ERRORF(r, "Failed to decode %s\n", name);
@@ -72,15 +67,13 @@
     }
 
     // Now decode part of the file
-    HaltingStream* stream = new HaltingStream(file, SkTMax(file->size() / 2, minBytes));
+    HaltingStream* stream = new HaltingStream(file, minBytes);
 
     // Note that we cheat and hold on to a pointer to stream, though it is owned by
     // partialCodec.
-    std::unique_ptr<SkCodec> partialCodec(SkCodec::MakeFromStream(std::unique_ptr<SkStream>(stream)));
+    auto partialCodec = SkCodec::MakeFromStream(std::unique_ptr<SkStream>(stream));
     if (!partialCodec) {
-        // Technically, this could be a small file where half the file is not
-        // enough.
-        ERRORF(r, "Failed to create codec for %s", name);
+        ERRORF(r, "Failed to create codec for %s with %zu bytes", name, minBytes);
         return;
     }
 
@@ -101,12 +94,14 @@
             return;
         }
 
-        // Append some data. The size is arbitrary, but deliberately different from
-        // the buffer size used by SkPngCodec.
-        stream->addNewData(1000);
+        stream->addNewData(increment);
     }
 
     while (true) {
+        // This imitates how Chromium calls getFrameCount before resuming a decode.
+        // Without this line, the test passes. With it, it fails when skia_use_wuffs
+        // is true.
+        partialCodec->getFrameCount();
         const SkCodec::Result result = partialCodec->incrementalDecode();
 
         if (result == SkCodec::kSuccess) {
@@ -120,15 +115,25 @@
             return;
         }
 
-        // Append some data. The size is arbitrary, but deliberately different from
-        // the buffer size used by SkPngCodec.
-        stream->addNewData(1000);
+        stream->addNewData(increment);
     }
 
     // compare to original
     compare_bitmaps(r, truth, incremental);
 }
 
+static void test_partial(skiatest::Reporter* r, const char* name, size_t minBytes = 0) {
+    sk_sp<SkData> file = GetResourceAsData(name);
+    if (!file) {
+        SkDebugf("missing resource %s\n", name);
+        return;
+    }
+
+    // This size is arbitrary, but deliberately different from the buffer size used by SkPngCodec.
+    constexpr size_t kIncrement = 1000;
+    test_partial(r, name, file, SkTMax(file->size() / 2, minBytes), kIncrement);
+}
+
 DEF_TEST(Codec_partial, r) {
 #if 0
     // FIXME (scroggo): SkPngCodec needs to use SkStreamBuffer in order to
@@ -149,6 +154,21 @@
     test_partial(r, "images/color_wheel.gif");
 }
 
+DEF_TEST(Codec_partialWuffs, r) {
+    const char* path = "images/alphabetAnim.gif";
+    auto file = GetResourceAsData(path);
+    if (!file) {
+        ERRORF(r, "missing %s", path);
+    } else {
+        // This is the end of the first frame. SkCodec will treat this as a
+        // single frame gif.
+        file = SkData::MakeSubset(file.get(), 0, 153);
+        // Start with 100 to get a partial decode, then add the rest of the
+        // first frame to decode a full image.
+        test_partial(r, path, file, 100, 53);
+    }
+}
+
 // Verify that when decoding an animated gif byte by byte we report the correct
 // fRequiredFrame as soon as getFrameInfo reports the frame.
 DEF_TEST(Codec_requiredFrame, r) {