// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/lib/ui/painting/image_decoder.h"

#include "flutter/common/task_runners.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/lib/ui/painting/multi_frame_codec.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/testing/dart_isolate_runner.h"
#include "flutter/testing/elf_loader.h"
#include "flutter/testing/fixture_test.h"
#include "flutter/testing/test_dart_native_resolver.h"
#include "flutter/testing/test_gl_surface.h"
#include "flutter/testing/testing.h"
#include "third_party/skia/include/codec/SkCodec.h"

namespace flutter {
namespace testing {

class TestIOManager final : public IOManager {
 public:
  explicit TestIOManager(fml::RefPtr<fml::TaskRunner> task_runner,
                         bool has_gpu_context = true)
      : gl_surface_(SkISize::Make(1, 1)),
        gl_context_(has_gpu_context ? gl_surface_.CreateGrContext() : nullptr),
        weak_gl_context_factory_(
            has_gpu_context
                ? std::make_unique<fml::WeakPtrFactory<GrDirectContext>>(
                      gl_context_.get())
                : nullptr),
        unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
            task_runner,
            fml::TimeDelta::FromNanoseconds(0))),
        runner_(task_runner),
        is_gpu_disabled_sync_switch_(std::make_shared<fml::SyncSwitch>()),
        weak_factory_(this) {
    FML_CHECK(task_runner->RunsTasksOnCurrentThread())
        << "The IO manager must be initialized its primary task runner. The "
           "test harness may not be set up correctly/safely.";
    weak_prototype_ = weak_factory_.GetWeakPtr();
  }

  ~TestIOManager() override {
    fml::AutoResetWaitableEvent latch;
    fml::TaskRunner::RunNowOrPostTask(runner_,
                                      [&latch, queue = unref_queue_]() {
                                        queue->Drain();
                                        latch.Signal();
                                      });
    latch.Wait();
  }

  // |IOManager|
  fml::WeakPtr<IOManager> GetWeakIOManager() const override {
    return weak_prototype_;
  }

  // |IOManager|
  fml::WeakPtr<GrDirectContext> GetResourceContext() const override {
    return weak_gl_context_factory_ ? weak_gl_context_factory_->GetWeakPtr()
                                    : fml::WeakPtr<GrDirectContext>{};
  }

  // |IOManager|
  fml::RefPtr<flutter::SkiaUnrefQueue> GetSkiaUnrefQueue() const override {
    return unref_queue_;
  }

  // |IOManager|
  std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch() override {
    did_access_is_gpu_disabled_sync_switch_ = true;
    return is_gpu_disabled_sync_switch_;
  }

  bool did_access_is_gpu_disabled_sync_switch_ = false;

 private:
  TestGLSurface gl_surface_;
  sk_sp<GrDirectContext> gl_context_;
  std::unique_ptr<fml::WeakPtrFactory<GrDirectContext>>
      weak_gl_context_factory_;
  fml::RefPtr<SkiaUnrefQueue> unref_queue_;
  fml::WeakPtr<TestIOManager> weak_prototype_;
  fml::RefPtr<fml::TaskRunner> runner_;
  std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch_;
  fml::WeakPtrFactory<TestIOManager> weak_factory_;

  FML_DISALLOW_COPY_AND_ASSIGN(TestIOManager);
};

static sk_sp<SkData> OpenFixtureAsSkData(const char* name) {
  auto fixtures_directory =
      fml::OpenDirectory(GetFixturesPath(), false, fml::FilePermission::kRead);
  if (!fixtures_directory.is_valid()) {
    return nullptr;
  }

  auto fixture_mapping =
      fml::FileMapping::CreateReadOnly(fixtures_directory, name);

  if (!fixture_mapping) {
    return nullptr;
  }

  SkData::ReleaseProc on_release = [](const void* ptr, void* context) -> void {
    delete reinterpret_cast<fml::FileMapping*>(context);
  };

  auto data = SkData::MakeWithProc(fixture_mapping->GetMapping(),
                                   fixture_mapping->GetSize(), on_release,
                                   fixture_mapping.get());

  if (!data) {
    return nullptr;
  }
  // The data is now owned by Skia.
  fixture_mapping.release();
  return data;
}

class ImageDecoderFixtureTest : public FixtureTest {};

TEST_F(ImageDecoderFixtureTest, CanCreateImageDecoder) {
  auto loop = fml::ConcurrentMessageLoop::Create();
  auto thread_task_runner = CreateNewThread();
  TaskRunners runners(GetCurrentTestName(),  // label
                      thread_task_runner,    // platform
                      thread_task_runner,    // raster
                      thread_task_runner,    // ui
                      thread_task_runner     // io

  );

  fml::AutoResetWaitableEvent latch;
  runners.GetIOTaskRunner()->PostTask([&]() {
    TestIOManager manager(runners.GetIOTaskRunner());
    ImageDecoder decoder(std::move(runners), loop->GetTaskRunner(),
                         manager.GetWeakIOManager());
    latch.Signal();
  });
  latch.Wait();
}

TEST_F(ImageDecoderFixtureTest, InvalidImageResultsError) {
  auto loop = fml::ConcurrentMessageLoop::Create();
  auto thread_task_runner = CreateNewThread();
  TaskRunners runners(GetCurrentTestName(),  // label
                      thread_task_runner,    // platform
                      thread_task_runner,    // raster
                      thread_task_runner,    // ui
                      thread_task_runner     // io
  );

  fml::AutoResetWaitableEvent latch;
  thread_task_runner->PostTask([&]() {
    TestIOManager manager(runners.GetIOTaskRunner());
    ImageDecoder decoder(runners, loop->GetTaskRunner(),
                         manager.GetWeakIOManager());

    auto data = OpenFixtureAsSkData("ThisDoesNotExist.jpg");
    ASSERT_FALSE(data);

    fml::RefPtr<ImageDescriptor> image_descriptor =
        fml::MakeRefCounted<ImageDescriptor>(std::move(data),
                                             std::unique_ptr<SkCodec>(nullptr));

    ImageDecoder::ImageResult callback = [&](SkiaGPUObject<SkImage> image) {
      ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
      ASSERT_FALSE(image.get());
      latch.Signal();
    };
    decoder.Decode(image_descriptor, 0, 0, callback);
  });
  latch.Wait();
}

TEST_F(ImageDecoderFixtureTest, ValidImageResultsInSuccess) {
  auto loop = fml::ConcurrentMessageLoop::Create();
  TaskRunners runners(GetCurrentTestName(),         // label
                      CreateNewThread("platform"),  // platform
                      CreateNewThread("raster"),    // raster
                      CreateNewThread("ui"),        // ui
                      CreateNewThread("io")         // io
  );

  fml::AutoResetWaitableEvent latch;

  std::unique_ptr<TestIOManager> io_manager;

  auto release_io_manager = [&]() {
    io_manager.reset();
    latch.Signal();
  };
  auto decode_image = [&]() {
    std::unique_ptr<ImageDecoder> image_decoder =
        std::make_unique<ImageDecoder>(runners, loop->GetTaskRunner(),
                                       io_manager->GetWeakIOManager());

    auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");

    ASSERT_TRUE(data);
    ASSERT_GE(data->size(), 0u);

    std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
    ASSERT_TRUE(codec);

    auto descriptor =
        fml::MakeRefCounted<ImageDescriptor>(std::move(data), std::move(codec));

    ImageDecoder::ImageResult callback = [&](SkiaGPUObject<SkImage> image) {
      ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
      ASSERT_TRUE(image.get());
      EXPECT_TRUE(io_manager->did_access_is_gpu_disabled_sync_switch_);
      runners.GetIOTaskRunner()->PostTask(release_io_manager);
    };
    EXPECT_FALSE(io_manager->did_access_is_gpu_disabled_sync_switch_);
    image_decoder->Decode(descriptor, descriptor->width(), descriptor->height(),
                          callback);
  };

  auto setup_io_manager_and_decode = [&]() {
    io_manager = std::make_unique<TestIOManager>(runners.GetIOTaskRunner());
    runners.GetUITaskRunner()->PostTask(decode_image);
  };

  runners.GetIOTaskRunner()->PostTask(setup_io_manager_and_decode);
  latch.Wait();
}

TEST_F(ImageDecoderFixtureTest, ExifDataIsRespectedOnDecode) {
  auto loop = fml::ConcurrentMessageLoop::Create();
  TaskRunners runners(GetCurrentTestName(),         // label
                      CreateNewThread("platform"),  // platform
                      CreateNewThread("raster"),    // raster
                      CreateNewThread("ui"),        // ui
                      CreateNewThread("io")         // io
  );

  fml::AutoResetWaitableEvent latch;

  std::unique_ptr<IOManager> io_manager;

  auto release_io_manager = [&]() {
    io_manager.reset();
    latch.Signal();
  };

  SkISize decoded_size = SkISize::MakeEmpty();
  auto decode_image = [&]() {
    std::unique_ptr<ImageDecoder> image_decoder =
        std::make_unique<ImageDecoder>(runners, loop->GetTaskRunner(),
                                       io_manager->GetWeakIOManager());

    auto data = OpenFixtureAsSkData("Horizontal.jpg");

    ASSERT_TRUE(data);
    ASSERT_GE(data->size(), 0u);

    std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
    ASSERT_TRUE(codec);

    auto descriptor =
        fml::MakeRefCounted<ImageDescriptor>(std::move(data), std::move(codec));

    ImageDecoder::ImageResult callback = [&](SkiaGPUObject<SkImage> image) {
      ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
      ASSERT_TRUE(image.get());
      decoded_size = image.get()->dimensions();
      runners.GetIOTaskRunner()->PostTask(release_io_manager);
    };
    image_decoder->Decode(descriptor, descriptor->width(), descriptor->height(),
                          callback);
  };

  auto setup_io_manager_and_decode = [&]() {
    io_manager = std::make_unique<TestIOManager>(runners.GetIOTaskRunner());
    runners.GetUITaskRunner()->PostTask(decode_image);
  };

  runners.GetIOTaskRunner()->PostTask(setup_io_manager_and_decode);

  latch.Wait();

  ASSERT_EQ(decoded_size.width(), 600);
  ASSERT_EQ(decoded_size.height(), 200);
}

TEST_F(ImageDecoderFixtureTest, CanDecodeWithoutAGPUContext) {
  auto loop = fml::ConcurrentMessageLoop::Create();
  TaskRunners runners(GetCurrentTestName(),         // label
                      CreateNewThread("platform"),  // platform
                      CreateNewThread("raster"),    // raster
                      CreateNewThread("ui"),        // ui
                      CreateNewThread("io")         // io
  );

  fml::AutoResetWaitableEvent latch;

  std::unique_ptr<IOManager> io_manager;

  auto release_io_manager = [&]() {
    io_manager.reset();
    latch.Signal();
  };

  auto decode_image = [&]() {
    std::unique_ptr<ImageDecoder> image_decoder =
        std::make_unique<ImageDecoder>(runners, loop->GetTaskRunner(),
                                       io_manager->GetWeakIOManager());

    auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");

    ASSERT_TRUE(data);
    ASSERT_GE(data->size(), 0u);

    std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
    ASSERT_TRUE(codec);

    auto descriptor =
        fml::MakeRefCounted<ImageDescriptor>(std::move(data), std::move(codec));

    ImageDecoder::ImageResult callback = [&](SkiaGPUObject<SkImage> image) {
      ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
      ASSERT_TRUE(image.get());
      runners.GetIOTaskRunner()->PostTask(release_io_manager);
    };
    image_decoder->Decode(descriptor, descriptor->width(), descriptor->height(),
                          callback);
  };

  auto setup_io_manager_and_decode = [&]() {
    io_manager =
        std::make_unique<TestIOManager>(runners.GetIOTaskRunner(), false);
    runners.GetUITaskRunner()->PostTask(decode_image);
  };

  runners.GetIOTaskRunner()->PostTask(setup_io_manager_and_decode);

  latch.Wait();
}

TEST_F(ImageDecoderFixtureTest, CanDecodeWithResizes) {
  const auto image_dimensions =
      SkImage::MakeFromEncoded(OpenFixtureAsSkData("DashInNooglerHat.jpg"))
          ->dimensions();

  ASSERT_FALSE(image_dimensions.isEmpty());

  ASSERT_NE(image_dimensions.width(), image_dimensions.height());

  auto loop = fml::ConcurrentMessageLoop::Create();
  TaskRunners runners(GetCurrentTestName(),         // label
                      CreateNewThread("platform"),  // platform
                      CreateNewThread("raster"),    // raster
                      CreateNewThread("ui"),        // ui
                      CreateNewThread("io")         // io
  );

  fml::AutoResetWaitableEvent latch;
  std::unique_ptr<IOManager> io_manager;
  std::unique_ptr<ImageDecoder> image_decoder;

  // Setup the IO manager.
  runners.GetIOTaskRunner()->PostTask([&]() {
    io_manager = std::make_unique<TestIOManager>(runners.GetIOTaskRunner());
    latch.Signal();
  });
  latch.Wait();

  // Setup the image decoder.
  runners.GetUITaskRunner()->PostTask([&]() {
    image_decoder = std::make_unique<ImageDecoder>(
        runners, loop->GetTaskRunner(), io_manager->GetWeakIOManager());

    latch.Signal();
  });
  latch.Wait();

  // Setup a generic decoding utility that gives us the final decoded size.
  auto decoded_size = [&](uint32_t target_width,
                          uint32_t target_height) -> SkISize {
    SkISize final_size = SkISize::MakeEmpty();
    runners.GetUITaskRunner()->PostTask([&]() {
      auto data = OpenFixtureAsSkData("DashInNooglerHat.jpg");

      ASSERT_TRUE(data);
      ASSERT_GE(data->size(), 0u);

      std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data);
      ASSERT_TRUE(codec);

      auto descriptor = fml::MakeRefCounted<ImageDescriptor>(std::move(data),
                                                             std::move(codec));

      ImageDecoder::ImageResult callback = [&](SkiaGPUObject<SkImage> image) {
        ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
        ASSERT_TRUE(image.get());
        final_size = image.get()->dimensions();
        latch.Signal();
      };
      image_decoder->Decode(descriptor, target_width, target_height, callback);
    });
    latch.Wait();
    return final_size;
  };

  ASSERT_EQ(SkISize::Make(3024, 4032), image_dimensions);
  ASSERT_EQ(decoded_size(3024, 4032), image_dimensions);
  ASSERT_EQ(decoded_size(100, 100), SkISize::Make(100, 100));

  // Destroy the IO manager
  runners.GetIOTaskRunner()->PostTask([&]() {
    io_manager.reset();
    latch.Signal();
  });
  latch.Wait();

  // Destroy the image decoder
  runners.GetUITaskRunner()->PostTask([&]() {
    image_decoder.reset();
    latch.Signal();
  });
  latch.Wait();
}

TEST_F(ImageDecoderFixtureTest, CanResizeWithoutDecode) {
  SkImageInfo info = {};
  size_t row_bytes;
  sk_sp<SkData> decompressed_data;
  SkISize image_dimensions = SkISize::MakeEmpty();
  {
    auto image =
        SkImage::MakeFromEncoded(OpenFixtureAsSkData("DashInNooglerHat.jpg"))
            ->makeRasterImage();
    image_dimensions = image->dimensions();
    SkPixmap pixmap;
    ASSERT_TRUE(image->peekPixels(&pixmap));
    info = SkImageInfo::MakeN32Premul(image_dimensions);
    row_bytes = pixmap.rowBytes();
    decompressed_data =
        SkData::MakeWithCopy(pixmap.writable_addr(), pixmap.computeByteSize());
  }

  // This is not susceptible to changes in the underlying image decoder.
  ASSERT_EQ(decompressed_data->size(), 48771072u);
  ASSERT_EQ(decompressed_data->size(),
            image_dimensions.width() * image_dimensions.height() * 4u);
  ASSERT_EQ(row_bytes, image_dimensions.width() * 4u);
  ASSERT_FALSE(image_dimensions.isEmpty());
  ASSERT_NE(image_dimensions.width(), image_dimensions.height());

  auto loop = fml::ConcurrentMessageLoop::Create();
  TaskRunners runners(GetCurrentTestName(),         // label
                      CreateNewThread("platform"),  // platform
                      CreateNewThread("raster"),    // raster
                      CreateNewThread("ui"),        // ui
                      CreateNewThread("io")         // io
  );

  fml::AutoResetWaitableEvent latch;
  std::unique_ptr<IOManager> io_manager;
  std::unique_ptr<ImageDecoder> image_decoder;

  // Setup the IO manager.
  runners.GetIOTaskRunner()->PostTask([&]() {
    io_manager = std::make_unique<TestIOManager>(runners.GetIOTaskRunner());
    latch.Signal();
  });
  latch.Wait();

  // Setup the image decoder.
  runners.GetUITaskRunner()->PostTask([&]() {
    image_decoder = std::make_unique<ImageDecoder>(
        runners, loop->GetTaskRunner(), io_manager->GetWeakIOManager());

    latch.Signal();
  });
  latch.Wait();

  // Setup a generic decoding utility that gives us the final decoded size.
  auto decoded_size = [&](uint32_t target_width,
                          uint32_t target_height) -> SkISize {
    SkISize final_size = SkISize::MakeEmpty();
    runners.GetUITaskRunner()->PostTask([&]() {
      ASSERT_TRUE(decompressed_data);
      ASSERT_GE(decompressed_data->size(), 0u);

      auto descriptor = fml::MakeRefCounted<ImageDescriptor>(decompressed_data,
                                                             info, row_bytes);

      ImageDecoder::ImageResult callback = [&](SkiaGPUObject<SkImage> image) {
        ASSERT_TRUE(runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
        ASSERT_TRUE(image.get());
        final_size = image.get()->dimensions();
        latch.Signal();
      };
      image_decoder->Decode(descriptor, target_width, target_height, callback);
    });
    latch.Wait();
    return final_size;
  };

  ASSERT_EQ(SkISize::Make(3024, 4032), image_dimensions);
  ASSERT_EQ(decoded_size(3024, 4032), image_dimensions);
  ASSERT_EQ(decoded_size(100, 100), SkISize::Make(100, 100));

  // Destroy the IO manager
  runners.GetIOTaskRunner()->PostTask([&]() {
    io_manager.reset();
    latch.Signal();
  });
  latch.Wait();

  // Destroy the image decoder
  runners.GetUITaskRunner()->PostTask([&]() {
    image_decoder.reset();
    latch.Signal();
  });
  latch.Wait();
}

// Verifies https://skia-review.googlesource.com/c/skia/+/259161 is present in
// Flutter.
TEST(ImageDecoderTest,
     VerifyCodecRepeatCountsForGifAndWebPAreConsistentWithLoopCounts) {
  auto gif_mapping = OpenFixtureAsSkData("hello_loop_2.gif");
  auto webp_mapping = OpenFixtureAsSkData("hello_loop_2.webp");

  ASSERT_TRUE(gif_mapping);
  ASSERT_TRUE(webp_mapping);

  auto gif_codec = SkCodec::MakeFromData(gif_mapping);
  auto webp_codec = SkCodec::MakeFromData(webp_mapping);

  ASSERT_TRUE(gif_codec);
  ASSERT_TRUE(webp_codec);

  // Both fixtures have a loop count of 2 which should lead to the repeat count
  // of 1
  ASSERT_EQ(gif_codec->getRepetitionCount(), 1);
  ASSERT_EQ(webp_codec->getRepetitionCount(), 1);
}

TEST(ImageDecoderTest, VerifySimpleDecoding) {
  auto data = OpenFixtureAsSkData("Horizontal.jpg");
  auto image = SkImage::MakeFromEncoded(data);
  ASSERT_TRUE(image != nullptr);
  ASSERT_EQ(SkISize::Make(600, 200), image->dimensions());

  auto codec = SkCodec::MakeFromData(data);
  ASSERT_TRUE(codec);
  auto descriptor =
      fml::MakeRefCounted<ImageDescriptor>(std::move(data), std::move(codec));

  ASSERT_EQ(ImageFromCompressedData(descriptor.get(), 6, 2,
                                    fml::tracing::TraceFlow(""))
                ->dimensions(),
            SkISize::Make(6, 2));
}

TEST(ImageDecoderTest, VerifySubpixelDecodingPreservesExifOrientation) {
  auto data = OpenFixtureAsSkData("Horizontal.jpg");
  auto codec = SkCodec::MakeFromData(data);
  ASSERT_TRUE(codec);
  auto descriptor =
      fml::MakeRefCounted<ImageDescriptor>(data, std::move(codec));

  auto image = SkImage::MakeFromEncoded(data);
  ASSERT_TRUE(image != nullptr);
  ASSERT_EQ(SkISize::Make(600, 200), image->dimensions());

  auto decode = [descriptor](uint32_t target_width, uint32_t target_height) {
    return ImageFromCompressedData(descriptor.get(), target_width,
                                   target_height, fml::tracing::TraceFlow(""));
  };

  auto expected_data = OpenFixtureAsSkData("Horizontal.png");
  ASSERT_TRUE(expected_data != nullptr);
  ASSERT_FALSE(expected_data->isEmpty());

  auto assert_image = [&](auto decoded_image) {
    ASSERT_EQ(decoded_image->dimensions(), SkISize::Make(300, 100));
    ASSERT_TRUE(decoded_image->encodeToData(SkEncodedImageFormat::kPNG, 100)
                    ->equals(expected_data.get()));
  };

  assert_image(decode(300, 100));
}

TEST_F(ImageDecoderFixtureTest,
       MultiFrameCodecCanBeCollectedBeforeIOTasksFinish) {
  // This test verifies that the MultiFrameCodec safely shares state between
  // tasks on the IO and UI runners, and does not allow unsafe memory access if
  // the UI object is collected while the IO thread still has pending decode
  // work. This could happen in a real application if the engine is collected
  // while a multi-frame image is decoding. To exercise this, the test:
  //   - Starts a Dart VM
  //   - Latches the IO task runner
  //   - Create a MultiFrameCodec for an animated gif pointed to a callback
  //     in the Dart fixture
  //   - Calls getNextFrame on the UI task runner
  //   - Collects the MultiFrameCodec object before unlatching the IO task
  //     runner.
  //   - Unlatches the IO task runner
  auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
  auto vm_data = vm_ref.GetVMData();

  auto gif_mapping = OpenFixtureAsSkData("hello_loop_2.gif");

  ASSERT_TRUE(gif_mapping);

  auto gif_codec = std::shared_ptr<SkCodecImageGenerator>(
      static_cast<SkCodecImageGenerator*>(
          SkCodecImageGenerator::MakeFromEncodedCodec(gif_mapping).release()));
  ASSERT_TRUE(gif_codec);

  TaskRunners runners(GetCurrentTestName(),         // label
                      CreateNewThread("platform"),  // platform
                      CreateNewThread("raster"),    // raster
                      CreateNewThread("ui"),        // ui
                      CreateNewThread("io")         // io
  );

  fml::AutoResetWaitableEvent latch;
  fml::AutoResetWaitableEvent io_latch;
  std::unique_ptr<TestIOManager> io_manager;

  // Setup the IO manager.
  runners.GetIOTaskRunner()->PostTask([&]() {
    io_manager = std::make_unique<TestIOManager>(runners.GetIOTaskRunner());
    latch.Signal();
  });
  latch.Wait();

  auto isolate =
      RunDartCodeInIsolate(vm_ref, settings, runners, "main", {},
                           GetFixturesPath(), io_manager->GetWeakIOManager());

  // Latch the IO task runner.
  runners.GetIOTaskRunner()->PostTask([&]() { io_latch.Wait(); });

  runners.GetUITaskRunner()->PostTask([&]() {
    fml::AutoResetWaitableEvent isolate_latch;
    fml::RefPtr<MultiFrameCodec> codec;
    EXPECT_TRUE(isolate->RunInIsolateScope([&]() -> bool {
      Dart_Handle library = Dart_RootLibrary();
      if (Dart_IsError(library)) {
        isolate_latch.Signal();
        return false;
      }
      Dart_Handle closure =
          Dart_GetField(library, Dart_NewStringFromCString("frameCallback"));
      if (Dart_IsError(closure) || !Dart_IsClosure(closure)) {
        isolate_latch.Signal();
        return false;
      }

      codec = fml::MakeRefCounted<MultiFrameCodec>(std::move(gif_codec));
      codec->getNextFrame(closure);
      codec = nullptr;
      isolate_latch.Signal();
      return true;
    }));
    isolate_latch.Wait();

    EXPECT_FALSE(codec);

    io_latch.Signal();

    latch.Signal();
  });
  latch.Wait();

  // Destroy the IO manager
  runners.GetIOTaskRunner()->PostTask([&]() {
    io_manager.reset();
    latch.Signal();
  });
  latch.Wait();
}

}  // namespace testing
}  // namespace flutter
