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) {