Add tests decoding files using 'idat' instead of 'mdat' (#2433)

diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index da1b0f9..0c67dbd 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -148,7 +148,7 @@
 
     add_avif_gtest(avifopaquetest)
     add_avif_gtest_with_data(avifpng16bittest)
-    add_avif_gtest(avifprogressivetest)
+    add_avif_gtest_with_data(avifprogressivetest)
     add_avif_gtest(avifrangetest)
     add_avif_gtest_with_data(avifreadimagetest)
     add_avif_internal_gtest(avifrgbtest)
diff --git a/tests/data/README.md b/tests/data/README.md
index 73fa12f..d424f07 100644
--- a/tests/data/README.md
+++ b/tests/data/README.md
@@ -712,6 +712,48 @@
 - For the wide color gamut version, choose Edit > Assign Profile... and set the color space to
   Rec.ITU-R BT.2020-1
 
+## Idat
+
+These files use the 'idat' box instead of the 'mdat' box to store data.
+
+### File [draw_points_idat.avif](draw_points_idat.avif)
+
+![](draw_points_idat.avif)
+
+License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE)
+
+Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat
+by running `./avifenc -q 100 ../tests/data/draw_points.png ../tests/data/draw_points_idat.avif` 
+
+### File [draw_points_idat_metasize0.avif](draw_points_idat_metasize0.avif)
+
+![](draw_points_idat_metasize0.avif)
+
+License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE)
+
+Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat
+after uncommenting the line under `// uncomment to make meta size zero` and running
+`./avifenc -q 100 ../tests/data/draw_points.png ../tests/data/draw_points_idat_metasize0.avif` 
+
+### File [draw_points_idat_progressive.avif](draw_points_idat_progressive.avif)
+
+![](draw_points_idat_progressive.avif)
+
+License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE)
+
+Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat
+by running `./avifenc -q 100 --progressive ../tests/data/draw_points.png ../tests/data/draw_points_idat_progressive.avif` 
+
+### File [draw_points_idat_progressive_metasize0.avif](draw_points_idat_progressive_metasize0.avif)
+
+![](draw_points_idat_progressive_metasize0.avif)
+
+License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE)
+
+Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat
+after uncommenting the line under `// uncomment to make meta size zero` and running
+`./avifenc -q 100 --progressive ../tests/data/draw_points.png ../tests/data/draw_points_idat_progressive_metasize0.avif` 
+
 ## Animated Images
 
 ### File [colors-animated-8bpc.avif](colors-animated-8bpc.avif)
diff --git a/tests/data/draw_points_idat.avif b/tests/data/draw_points_idat.avif
new file mode 100644
index 0000000..877e654
--- /dev/null
+++ b/tests/data/draw_points_idat.avif
Binary files differ
diff --git a/tests/data/draw_points_idat_metasize0.avif b/tests/data/draw_points_idat_metasize0.avif
new file mode 100644
index 0000000..bf78bfd
--- /dev/null
+++ b/tests/data/draw_points_idat_metasize0.avif
Binary files differ
diff --git a/tests/data/draw_points_idat_progressive.avif b/tests/data/draw_points_idat_progressive.avif
new file mode 100644
index 0000000..fe8b23d
--- /dev/null
+++ b/tests/data/draw_points_idat_progressive.avif
Binary files differ
diff --git a/tests/data/draw_points_idat_progressive_metasize0.avif b/tests/data/draw_points_idat_progressive_metasize0.avif
new file mode 100644
index 0000000..2eb8614
--- /dev/null
+++ b/tests/data/draw_points_idat_progressive_metasize0.avif
Binary files differ
diff --git a/tests/gtest/avifdecodetest.cc b/tests/gtest/avifdecodetest.cc
index b16f0d9..e4b5a96 100644
--- a/tests/gtest/avifdecodetest.cc
+++ b/tests/gtest/avifdecodetest.cc
@@ -41,6 +41,34 @@
   ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_INVALID_FTYP);
 }
 
+TEST(AvifDecodeTest, Idat) {
+  if (!testutil::Av1DecoderAvailable()) {
+    GTEST_SKIP() << "AV1 Codec unavailable, skip test.";
+  }
+
+  const ImagePtr original = testutil::ReadImage(data_path, "draw_points.png");
+
+  for (const std::string file_name :
+       {"draw_points_idat.avif", "draw_points_idat_metasize0.avif",
+        "draw_points_idat_progressive.avif",
+        "draw_points_idat_progressive_metasize0.avif"}) {
+    SCOPED_TRACE(file_name);
+    DecoderPtr decoder(avifDecoderCreate());
+    ASSERT_NE(decoder, nullptr);
+    ASSERT_EQ(avifDecoderSetIOFile(
+                  decoder.get(), (std::string(data_path) + file_name).c_str()),
+              AVIF_RESULT_OK);
+    ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
+    EXPECT_EQ(decoder->alphaPresent, AVIF_TRUE);
+    EXPECT_EQ(decoder->imageSequenceTrackPresent, AVIF_FALSE);
+    ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
+    EXPECT_NE(decoder->image->alphaPlane, nullptr);
+    EXPECT_GT(decoder->image->alphaRowBytes, 0u);
+
+    EXPECT_EQ(testutil::GetPsnr(*original, *decoder->image), 99.0);
+  }
+}
+
 // From https://crbug.com/334281983.
 TEST(AvifDecodeTest, PeekCompatibleFileTypeBad1) {
   constexpr uint8_t kData[] = {0x00, 0x00, 0x00, 0x1c, 0x66,
diff --git a/tests/gtest/avifprogressivetest.cc b/tests/gtest/avifprogressivetest.cc
index 4cb92da..ca25187 100644
--- a/tests/gtest/avifprogressivetest.cc
+++ b/tests/gtest/avifprogressivetest.cc
@@ -8,6 +8,9 @@
 namespace avif {
 namespace {
 
+// Used to pass the data folder path to the GoogleTest suites.
+const char* data_path = nullptr;
+
 class ProgressiveTest : public testing::Test {
  protected:
   static constexpr uint32_t kImageSize = 256;
@@ -30,9 +33,9 @@
     testutil::FillImageGradient(image_.get());
   }
 
-  void TestDecode(uint32_t expect_width, uint32_t expect_height) {
-    ASSERT_EQ(avifDecoderSetIOMemory(decoder_.get(), encoded_avif_.data,
-                                     encoded_avif_.size),
+  void TestDecode(uint8_t* data, size_t size, uint32_t expect_width,
+                  uint32_t expect_height) {
+    ASSERT_EQ(avifDecoderSetIOMemory(decoder_.get(), data, size),
               AVIF_RESULT_OK);
     ASSERT_EQ(avifDecoderParse(decoder_.get()), AVIF_RESULT_OK);
     ASSERT_EQ(decoder_->progressiveState, AVIF_PROGRESSIVE_STATE_ACTIVE);
@@ -46,6 +49,11 @@
       ASSERT_EQ(decoder_->image->height, expect_height);
       // TODO(wtc): Check avifDecoderNthImageMaxExtent().
     }
+  }
+
+  void TestDecode(uint32_t expect_width, uint32_t expect_height) {
+    TestDecode(encoded_avif_.data, encoded_avif_.size, expect_width,
+               expect_height);
 
     // TODO(wtc): Check decoder_->image and image_ are similar, and better
     // quality layer is more similar.
@@ -169,5 +177,50 @@
             AVIF_RESULT_INVALID_ARGUMENT);
 }
 
+// Test progressive decoding with files that use 'idat' (inside the 'meta') box
+// instead of 'mdat' to store the image data. Note that for now (as of v1.1.1)
+// the decoder waits to have the full meta box available before parsing it, so
+// incremental decoding is not really possible and progressive decoding makes
+// little sense. But this checks that the files are still processed correctly.
+TEST(DecodeProgressiveTest, DecodeIdat) {
+  const ImagePtr original = testutil::ReadImage(data_path, "draw_points.png");
+
+  for (const std::string file_name :
+       {"draw_points_idat_progressive.avif",
+        "draw_points_idat_progressive_metasize0.avif"}) {
+    SCOPED_TRACE(file_name);
+    const int expected_layer_count = 2;
+
+    DecoderPtr decoder(avifDecoderCreate());
+    decoder->allowProgressive = true;
+    ASSERT_EQ(avifDecoderSetIOFile(
+                  decoder.get(), (std::string(data_path) + file_name).c_str()),
+              AVIF_RESULT_OK);
+    ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
+    ASSERT_EQ(decoder->progressiveState, AVIF_PROGRESSIVE_STATE_ACTIVE);
+    ASSERT_EQ(static_cast<uint32_t>(decoder->imageCount), expected_layer_count);
+
+    for (uint32_t layer = 0; layer < expected_layer_count; ++layer) {
+      ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
+      ASSERT_EQ(decoder->image->width, original->width);
+      ASSERT_EQ(decoder->image->height, original->height);
+    }
+    ASSERT_EQ(avifDecoderNextImage(decoder.get()),
+              AVIF_RESULT_NO_IMAGES_REMAINING);
+  }
+}
+
 }  // namespace
 }  // namespace avif
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  if (argc != 2) {
+    std::cerr << "There must be exactly one argument containing the path to "
+                 "the test data folder"
+              << std::endl;
+    return 1;
+  }
+  avif::data_path = argv[1];
+  return RUN_ALL_TESTS();
+}