// 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/shell/common/engine.h"

#include <cstring>

#include "flutter/common/constants.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/shell_test.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/testing/fixture_test.h"
#include "flutter/testing/testing.h"
#include "fml/mapping.h"
#include "gmock/gmock.h"
#include "lib/ui/text/font_collection.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "runtime/isolate_configuration.h"
#include "shell/common/run_configuration.h"

namespace flutter {

namespace {

using ::testing::Invoke;
using ::testing::ReturnRef;

fml::AutoResetWaitableEvent native_latch;

void PostSync(const fml::RefPtr<fml::TaskRunner>& task_runner,
              const fml::closure& task) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(task_runner, [&latch, &task] {
    task();
    latch.Signal();
  });
  latch.Wait();
}

class FontManifestAssetResolver : public AssetResolver {
 public:
  FontManifestAssetResolver() {}

  bool IsValid() const override { return true; }

  bool IsValidAfterAssetManagerChange() const override { return true; }

  AssetResolver::AssetResolverType GetType() const override {
    return AssetResolver::AssetResolverType::kApkAssetProvider;
  }

  mutable size_t mapping_call_count = 0u;
  std::unique_ptr<fml::Mapping> GetAsMapping(
      const std::string& asset_name) const override {
    mapping_call_count++;
    if (asset_name == "FontManifest.json") {
      return std::make_unique<fml::DataMapping>("[{},{},{}]");
    }
    return nullptr;
  }

  std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
      const std::string& asset_pattern,
      const std::optional<std::string>& subdir) const override {
    return {};
  };

  bool operator==(const AssetResolver& other) const override {
    auto mapping = GetAsMapping("FontManifest.json");
    return memcmp(other.GetAsMapping("FontManifest.json")->GetMapping(),
                  mapping->GetMapping(), mapping->GetSize()) == 0;
  }
};

class MockDelegate : public Engine::Delegate {
 public:
  MOCK_METHOD(void,
              OnEngineUpdateSemantics,
              (SemanticsNodeUpdates, CustomAccessibilityActionUpdates),
              (override));
  MOCK_METHOD(void,
              OnEngineHandlePlatformMessage,
              (std::unique_ptr<PlatformMessage>),
              (override));
  MOCK_METHOD(void, OnPreEngineRestart, (), (override));
  MOCK_METHOD(void, OnRootIsolateCreated, (), (override));
  MOCK_METHOD(void,
              UpdateIsolateDescription,
              (const std::string, int64_t),
              (override));
  MOCK_METHOD(void, SetNeedsReportTimings, (bool), (override));
  MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
              ComputePlatformResolvedLocale,
              (const std::vector<std::string>&),
              (override));
  MOCK_METHOD(void, RequestDartDeferredLibrary, (intptr_t), (override));
  MOCK_METHOD(fml::TimePoint, GetCurrentTimePoint, (), (override));
  MOCK_METHOD(const std::shared_ptr<PlatformMessageHandler>&,
              GetPlatformMessageHandler,
              (),
              (const, override));
  MOCK_METHOD(void, OnEngineChannelUpdate, (std::string, bool), (override));
  MOCK_METHOD(double,
              GetScaledFontSize,
              (double font_size, int configuration_id),
              (const, override));
};

class MockResponse : public PlatformMessageResponse {
 public:
  MOCK_METHOD(void, Complete, (std::unique_ptr<fml::Mapping> data), (override));
  MOCK_METHOD(void, CompleteEmpty, (), (override));
};

class MockRuntimeDelegate : public RuntimeDelegate {
 public:
  MOCK_METHOD(std::string, DefaultRouteName, (), (override));
  MOCK_METHOD(void, ScheduleFrame, (bool), (override));
  MOCK_METHOD(void, EndWarmUpFrame, (), (override));
  MOCK_METHOD(void,
              Render,
              (int64_t, std::unique_ptr<flutter::LayerTree>, float),
              (override));
  MOCK_METHOD(void,
              UpdateSemantics,
              (SemanticsNodeUpdates, CustomAccessibilityActionUpdates),
              (override));
  MOCK_METHOD(void,
              HandlePlatformMessage,
              (std::unique_ptr<PlatformMessage>),
              (override));
  MOCK_METHOD(FontCollection&, GetFontCollection, (), (override));
  MOCK_METHOD(std::shared_ptr<AssetManager>, GetAssetManager, (), (override));
  MOCK_METHOD(void, OnRootIsolateCreated, (), (override));
  MOCK_METHOD(void,
              UpdateIsolateDescription,
              (const std::string, int64_t),
              (override));
  MOCK_METHOD(void, SetNeedsReportTimings, (bool), (override));
  MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
              ComputePlatformResolvedLocale,
              (const std::vector<std::string>&),
              (override));
  MOCK_METHOD(void, RequestDartDeferredLibrary, (intptr_t), (override));
  MOCK_METHOD(std::weak_ptr<PlatformMessageHandler>,
              GetPlatformMessageHandler,
              (),
              (const, override));
  MOCK_METHOD(void, SendChannelUpdate, (std::string, bool), (override));
  MOCK_METHOD(double,
              GetScaledFontSize,
              (double font_size, int configuration_id),
              (const, override));
};

class MockRuntimeController : public RuntimeController {
 public:
  MockRuntimeController(RuntimeDelegate& client,
                        const TaskRunners& p_task_runners)
      : RuntimeController(client, p_task_runners) {}
  MOCK_METHOD(bool, IsRootIsolateRunning, (), (override));
  MOCK_METHOD(bool,
              DispatchPlatformMessage,
              (std::unique_ptr<PlatformMessage>),
              (override));
  MOCK_METHOD(void,
              LoadDartDeferredLibraryError,
              (intptr_t, const std::string, bool),
              (override));
  MOCK_METHOD(DartVM*, GetDartVM, (), (const, override));
  MOCK_METHOD(bool, NotifyIdle, (fml::TimeDelta), (override));
};

class MockAnimatorDelegate : public Animator::Delegate {
 public:
  /* Animator::Delegate */
  MOCK_METHOD(void,
              OnAnimatorBeginFrame,
              (fml::TimePoint frame_target_time, uint64_t frame_number),
              (override));
  MOCK_METHOD(void,
              OnAnimatorNotifyIdle,
              (fml::TimeDelta deadline),
              (override));
  MOCK_METHOD(void,
              OnAnimatorUpdateLatestFrameTargetTime,
              (fml::TimePoint frame_target_time),
              (override));
  MOCK_METHOD(void,
              OnAnimatorDraw,
              (std::shared_ptr<FramePipeline> pipeline),
              (override));
  MOCK_METHOD(void,
              OnAnimatorDrawLastLayerTrees,
              (std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder),
              (override));
};

class MockPlatformMessageHandler : public PlatformMessageHandler {
 public:
  MOCK_METHOD(void,
              HandlePlatformMessage,
              (std::unique_ptr<PlatformMessage> message),
              (override));
  MOCK_METHOD(bool,
              DoesHandlePlatformMessageOnPlatformThread,
              (),
              (const, override));
  MOCK_METHOD(void,
              InvokePlatformMessageResponseCallback,
              (int response_id, std::unique_ptr<fml::Mapping> mapping),
              (override));
  MOCK_METHOD(void,
              InvokePlatformMessageEmptyResponseCallback,
              (int response_id),
              (override));
};

class MockFontCollection : public FontCollection {
 public:
  MOCK_METHOD(void,
              RegisterFonts,
              (const std::shared_ptr<AssetManager>& asset_manager),
              (override));
};

std::unique_ptr<PlatformMessage> MakePlatformMessage(
    const std::string& channel,
    const std::map<std::string, std::string>& values,
    const fml::RefPtr<PlatformMessageResponse>& response) {
  rapidjson::Document document;
  auto& allocator = document.GetAllocator();
  document.SetObject();

  for (const auto& pair : values) {
    rapidjson::Value key(pair.first.c_str(), strlen(pair.first.c_str()),
                         allocator);
    rapidjson::Value value(pair.second.c_str(), strlen(pair.second.c_str()),
                           allocator);
    document.AddMember(key, value, allocator);
  }

  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  document.Accept(writer);
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buffer.GetString());

  std::unique_ptr<PlatformMessage> message = std::make_unique<PlatformMessage>(
      channel, fml::MallocMapping::Copy(data, buffer.GetSize()), response);
  return message;
}

class EngineTest : public testing::FixtureTest {
 public:
  EngineTest()
      : thread_host_("EngineTest",
                     ThreadHost::Type::kPlatform | ThreadHost::Type::kIo |
                         ThreadHost::Type::kUi | ThreadHost::Type::kRaster),
        task_runners_({
            "EngineTest",
            thread_host_.platform_thread->GetTaskRunner(),  // platform
            thread_host_.raster_thread->GetTaskRunner(),    // raster
            thread_host_.ui_thread->GetTaskRunner(),        // ui
            thread_host_.io_thread->GetTaskRunner()         // io
        }) {}

  void PostUITaskSync(const std::function<void()>& function) {
    fml::AutoResetWaitableEvent latch;
    task_runners_.GetUITaskRunner()->PostTask([&] {
      function();
      latch.Signal();
    });
    latch.Wait();
  }

 protected:
  void SetUp() override {
    settings_ = CreateSettingsForFixture();
    dispatcher_maker_ = [](PointerDataDispatcher::Delegate&) {
      return nullptr;
    };
  }

  MockDelegate delegate_;
  PointerDataDispatcherMaker dispatcher_maker_;
  ThreadHost thread_host_;
  TaskRunners task_runners_;
  Settings settings_;
  std::unique_ptr<Animator> animator_;
  fml::WeakPtr<IOManager> io_manager_;
  std::unique_ptr<RuntimeController> runtime_controller_;
  std::shared_ptr<fml::ConcurrentTaskRunner> image_decoder_task_runner_;
  fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate_;
};

// A class that can launch an Engine with the specified Engine::Delegate.
//
// To use this class, contruct this class with Create, call Run, and use the
// engine with EngineTaskSync().
class EngineContext {
 public:
  using EngineCallback = std::function<void(Engine&)>;

  [[nodiscard]] static std::unique_ptr<EngineContext> Create(
      Engine::Delegate& delegate,       //
      Settings settings,                //
      const TaskRunners& task_runners,  //
      std::unique_ptr<Animator> animator) {
    auto [vm, isolate_snapshot] = Shell::InferVmInitDataFromSettings(settings);
    FML_CHECK(vm) << "Must be able to initialize the VM.";
    // Construct the class with `new` because `make_unique` has no access to the
    // private constructor.
    EngineContext* raw_pointer =
        new EngineContext(delegate, settings, task_runners, std::move(animator),
                          std::move(vm), isolate_snapshot);
    return std::unique_ptr<EngineContext>(raw_pointer);
  }

  void Run(RunConfiguration configuration) {
    PostSync(task_runners_.GetUITaskRunner(), [this, &configuration] {
      Engine::RunStatus run_status = engine_->Run(std::move(configuration));
      FML_CHECK(run_status == Engine::RunStatus::Success)
          << "Engine failed to run.";
      (void)run_status;  // Suppress unused-variable warning
    });
  }

  // Run a task that operates the Engine on the UI thread, and wait for the
  // task to end.
  //
  // If called on the UI thread, the task is executed synchronously.
  void EngineTaskSync(EngineCallback task) {
    ASSERT_TRUE(engine_);
    ASSERT_TRUE(task);
    auto runner = task_runners_.GetUITaskRunner();
    if (runner->RunsTasksOnCurrentThread()) {
      task(*engine_);
    } else {
      PostSync(task_runners_.GetUITaskRunner(), [&]() { task(*engine_); });
    }
  }

  ~EngineContext() {
    PostSync(task_runners_.GetUITaskRunner(), [this] { engine_.reset(); });
  }

 private:
  EngineContext(Engine::Delegate& delegate,          //
                Settings settings,                   //
                const TaskRunners& task_runners,     //
                std::unique_ptr<Animator> animator,  //
                DartVMRef vm,                        //
                fml::RefPtr<const DartSnapshot> isolate_snapshot)
      : task_runners_(task_runners), vm_(std::move(vm)) {
    PostSync(task_runners.GetUITaskRunner(), [this, &settings, &animator,
                                              &delegate, &isolate_snapshot] {
      auto dispatcher_maker =
          [](DefaultPointerDataDispatcher::Delegate& delegate) {
            return std::make_unique<DefaultPointerDataDispatcher>(delegate);
          };
      engine_ = std::make_unique<Engine>(
          /*delegate=*/delegate,
          /*dispatcher_maker=*/dispatcher_maker,
          /*vm=*/*&vm_,
          /*isolate_snapshot=*/std::move(isolate_snapshot),
          /*task_runners=*/task_runners_,
          /*platform_data=*/PlatformData(),
          /*settings=*/settings,
          /*animator=*/std::move(animator),
          /*io_manager=*/io_manager_,
          /*unref_queue=*/nullptr,
          /*snapshot_delegate=*/snapshot_delegate_,
          /*volatile_path_tracker=*/nullptr,
          /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
    });
  }

  TaskRunners task_runners_;
  DartVMRef vm_;
  std::unique_ptr<Engine> engine_;

  fml::WeakPtr<IOManager> io_manager_;
  fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate_;
};
}  // namespace

TEST_F(EngineTest, Create) {
  PostUITaskSync([this] {
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(runtime_controller_),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());
    EXPECT_TRUE(engine);
  });
}

TEST_F(EngineTest, DispatchPlatformMessageUnknown) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
        .WillRepeatedly(::testing::Return(false));
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    fml::RefPtr<PlatformMessageResponse> response =
        fml::MakeRefCounted<MockResponse>();
    std::unique_ptr<PlatformMessage> message =
        std::make_unique<PlatformMessage>("foo", response);
    engine->DispatchPlatformMessage(std::move(message));
  });
}

TEST_F(EngineTest, DispatchPlatformMessageInitialRoute) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
        .WillRepeatedly(::testing::Return(false));
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    fml::RefPtr<PlatformMessageResponse> response =
        fml::MakeRefCounted<MockResponse>();
    std::map<std::string, std::string> values{
        {"method", "setInitialRoute"},
        {"args", "test_initial_route"},
    };
    std::unique_ptr<PlatformMessage> message =
        MakePlatformMessage("flutter/navigation", values, response);
    engine->DispatchPlatformMessage(std::move(message));
    EXPECT_EQ(engine->InitialRoute(), "test_initial_route");
  });
}

TEST_F(EngineTest, DispatchPlatformMessageInitialRouteIgnored) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
        .WillRepeatedly(::testing::Return(true));
    EXPECT_CALL(*mock_runtime_controller, DispatchPlatformMessage(::testing::_))
        .WillRepeatedly(::testing::Return(true));
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    fml::RefPtr<PlatformMessageResponse> response =
        fml::MakeRefCounted<MockResponse>();
    std::map<std::string, std::string> values{
        {"method", "setInitialRoute"},
        {"args", "test_initial_route"},
    };
    std::unique_ptr<PlatformMessage> message =
        MakePlatformMessage("flutter/navigation", values, response);
    engine->DispatchPlatformMessage(std::move(message));
    EXPECT_EQ(engine->InitialRoute(), "");
  });
}

TEST_F(EngineTest, SpawnSharesFontLibrary) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    auto vm_ref = DartVMRef::Create(settings_);
    EXPECT_CALL(*mock_runtime_controller, GetDartVM())
        .WillRepeatedly(::testing::Return(vm_ref.get()));
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    auto spawn =
        engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
                      std::string(), io_manager_, snapshot_delegate_, nullptr);
    EXPECT_TRUE(spawn != nullptr);
    EXPECT_EQ(&engine->GetFontCollection(), &spawn->GetFontCollection());
  });
}

TEST_F(EngineTest, SpawnWithCustomInitialRoute) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    auto vm_ref = DartVMRef::Create(settings_);
    EXPECT_CALL(*mock_runtime_controller, GetDartVM())
        .WillRepeatedly(::testing::Return(vm_ref.get()));
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    auto spawn =
        engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr, "/foo",
                      io_manager_, snapshot_delegate_, nullptr);
    EXPECT_TRUE(spawn != nullptr);
    ASSERT_EQ("/foo", spawn->InitialRoute());
  });
}

TEST_F(EngineTest, SpawnWithCustomSettings) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    auto vm_ref = DartVMRef::Create(settings_);
    EXPECT_CALL(*mock_runtime_controller, GetDartVM())
        .WillRepeatedly(::testing::Return(vm_ref.get()));
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    Settings custom_settings = settings_;
    custom_settings.persistent_isolate_data =
        std::make_shared<fml::DataMapping>("foo");
    auto spawn =
        engine->Spawn(delegate_, dispatcher_maker_, custom_settings, nullptr,
                      std::string(), io_manager_, snapshot_delegate_, nullptr);
    EXPECT_TRUE(spawn != nullptr);
    auto new_persistent_isolate_data =
        const_cast<RuntimeController*>(spawn->GetRuntimeController())
            ->GetPersistentIsolateData();
    EXPECT_EQ(custom_settings.persistent_isolate_data->GetMapping(),
              new_persistent_isolate_data->GetMapping());
    EXPECT_EQ(custom_settings.persistent_isolate_data->GetSize(),
              new_persistent_isolate_data->GetSize());
  });
}

TEST_F(EngineTest, PassesLoadDartDeferredLibraryErrorToRuntime) {
  PostUITaskSync([this] {
    intptr_t error_id = 123;
    const std::string error_message = "error message";
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
        .WillRepeatedly(::testing::Return(true));
    EXPECT_CALL(*mock_runtime_controller,
                LoadDartDeferredLibraryError(error_id, error_message, true))
        .Times(1);
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    engine->LoadDartDeferredLibraryError(error_id, error_message, true);
  });
}

TEST_F(EngineTest, AnimatorAcceptsMultipleRenders) {
  MockAnimatorDelegate animator_delegate;
  std::unique_ptr<EngineContext> engine_context;

  std::shared_ptr<PlatformMessageHandler> platform_message_handler =
      std::make_shared<MockPlatformMessageHandler>();
  EXPECT_CALL(delegate_, GetPlatformMessageHandler)
      .WillOnce(ReturnRef(platform_message_handler));
  fml::AutoResetWaitableEvent draw_latch;
  EXPECT_CALL(animator_delegate, OnAnimatorDraw)
      .WillOnce(
          Invoke([&draw_latch](const std::shared_ptr<FramePipeline>& pipeline) {
            auto status =
                pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
                  EXPECT_EQ(item->layer_tree_tasks.size(), 2u);
                  EXPECT_EQ(item->layer_tree_tasks[0]->view_id, 1);
                  EXPECT_EQ(item->layer_tree_tasks[1]->view_id, 2);
                });
            EXPECT_EQ(status, PipelineConsumeResult::Done);
            draw_latch.Signal();
          }));
  EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
      .WillOnce(Invoke([&engine_context](fml::TimePoint frame_target_time,
                                         uint64_t frame_number) {
        engine_context->EngineTaskSync([&](Engine& engine) {
          engine.BeginFrame(frame_target_time, frame_number);
        });
      }));

  native_latch.Reset();
  AddNativeCallback("NotifyNative", [](auto args) { native_latch.Signal(); });

  std::unique_ptr<Animator> animator;
  PostSync(task_runners_.GetUITaskRunner(),
           [&animator, &animator_delegate, &task_runners = task_runners_] {
             animator = std::make_unique<Animator>(
                 animator_delegate, task_runners,
                 static_cast<std::unique_ptr<VsyncWaiter>>(
                     std::make_unique<testing::ConstantFiringVsyncWaiter>(
                         task_runners)));
           });

  engine_context = EngineContext::Create(delegate_, settings_, task_runners_,
                                         std::move(animator));
  auto configuration = RunConfiguration::InferFromSettings(settings_);
  configuration.SetEntrypoint("onDrawFrameRenderAllViews");
  engine_context->Run(std::move(configuration));

  engine_context->EngineTaskSync([](Engine& engine) {
    engine.AddView(1, ViewportMetrics{1, 10, 10, 22, 0});
    engine.AddView(2, ViewportMetrics{1, 10, 10, 22, 0});
  });

  native_latch.Wait();

  engine_context->EngineTaskSync(
      [](Engine& engine) { engine.ScheduleFrame(); });
  draw_latch.Wait();
}

// The animator should submit to the pipeline the implicit view rendered in a
// warm up frame if there's already a continuation (i.e. Animator::BeginFrame
// has been called)
TEST_F(EngineTest, AnimatorSubmitWarmUpImplicitView) {
  MockAnimatorDelegate animator_delegate;
  std::unique_ptr<EngineContext> engine_context;

  std::shared_ptr<PlatformMessageHandler> platform_message_handler =
      std::make_shared<MockPlatformMessageHandler>();
  EXPECT_CALL(delegate_, GetPlatformMessageHandler)
      .WillOnce(ReturnRef(platform_message_handler));

  fml::AutoResetWaitableEvent continuation_ready_latch;
  fml::AutoResetWaitableEvent draw_latch;
  EXPECT_CALL(animator_delegate, OnAnimatorDraw)
      .WillOnce(Invoke([&draw_latch](
                           const std::shared_ptr<FramePipeline>& pipeline) {
        auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
          EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
          EXPECT_EQ(item->layer_tree_tasks[0]->view_id, kFlutterImplicitViewId);
        });
        EXPECT_EQ(status, PipelineConsumeResult::Done);
        draw_latch.Signal();
      }));
  EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
      .WillRepeatedly(
          Invoke([&engine_context, &continuation_ready_latch](
                     fml::TimePoint frame_target_time, uint64_t frame_number) {
            continuation_ready_latch.Signal();
            engine_context->EngineTaskSync([&](Engine& engine) {
              engine.BeginFrame(frame_target_time, frame_number);
            });
          }));

  std::unique_ptr<Animator> animator;
  PostSync(task_runners_.GetUITaskRunner(),
           [&animator, &animator_delegate, &task_runners = task_runners_] {
             animator = std::make_unique<Animator>(
                 animator_delegate, task_runners,
                 static_cast<std::unique_ptr<VsyncWaiter>>(
                     std::make_unique<testing::ConstantFiringVsyncWaiter>(
                         task_runners)));
           });

  engine_context = EngineContext::Create(delegate_, settings_, task_runners_,
                                         std::move(animator));

  engine_context->EngineTaskSync([](Engine& engine) {
    // Schedule a frame to trigger Animator::BeginFrame to create a
    // continuation. The continuation needs to be available before `Engine::Run`
    // since the Dart program immediately schedules a warm up frame.
    engine.ScheduleFrame(true);
    // Add the implicit view so that the engine recognizes it and that its
    // metrics is not empty.
    engine.AddView(kFlutterImplicitViewId, ViewportMetrics{1.0, 10, 10, 1, 0});
  });
  continuation_ready_latch.Wait();

  auto configuration = RunConfiguration::InferFromSettings(settings_);
  configuration.SetEntrypoint("renderWarmUpImplicitView");
  engine_context->Run(std::move(configuration));

  draw_latch.Wait();
}

TEST_F(EngineTest, SpawnedEngineInheritsAssetManager) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    auto vm_ref = DartVMRef::Create(settings_);
    EXPECT_CALL(*mock_runtime_controller, GetDartVM())
        .WillRepeatedly(::testing::Return(vm_ref.get()));

    // auto mock_font_collection = std::make_shared<MockFontCollection>();
    // EXPECT_CALL(*mock_font_collection, RegisterFonts(::testing::_))
    //     .WillOnce(::testing::Return());
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/std::make_shared<FontCollection>(),
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    EXPECT_EQ(engine->GetAssetManager(), nullptr);

    auto asset_manager = std::make_shared<AssetManager>();
    asset_manager->PushBack(std::make_unique<FontManifestAssetResolver>());
    engine->UpdateAssetManager(asset_manager);
    EXPECT_EQ(engine->GetAssetManager(), asset_manager);

    auto spawn =
        engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
                      std::string(), io_manager_, snapshot_delegate_, nullptr);
    EXPECT_TRUE(spawn != nullptr);
    EXPECT_EQ(engine->GetAssetManager(), spawn->GetAssetManager());
  });
}

TEST_F(EngineTest, UpdateAssetManagerWithEqualManagers) {
  PostUITaskSync([this] {
    MockRuntimeDelegate client;
    auto mock_runtime_controller =
        std::make_unique<MockRuntimeController>(client, task_runners_);
    auto vm_ref = DartVMRef::Create(settings_);
    EXPECT_CALL(*mock_runtime_controller, GetDartVM())
        .WillRepeatedly(::testing::Return(vm_ref.get()));

    auto mock_font_collection = std::make_shared<MockFontCollection>();
    EXPECT_CALL(*mock_font_collection, RegisterFonts(::testing::_))
        .WillOnce(::testing::Return());
    auto engine = std::make_unique<Engine>(
        /*delegate=*/delegate_,
        /*dispatcher_maker=*/dispatcher_maker_,
        /*image_decoder_task_runner=*/image_decoder_task_runner_,
        /*task_runners=*/task_runners_,
        /*settings=*/settings_,
        /*animator=*/std::move(animator_),
        /*io_manager=*/io_manager_,
        /*font_collection=*/mock_font_collection,
        /*runtime_controller=*/std::move(mock_runtime_controller),
        /*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

    EXPECT_EQ(engine->GetAssetManager(), nullptr);

    auto asset_manager = std::make_shared<AssetManager>();
    asset_manager->PushBack(std::make_unique<FontManifestAssetResolver>());

    auto asset_manager_2 = std::make_shared<AssetManager>();
    asset_manager_2->PushBack(std::make_unique<FontManifestAssetResolver>());

    EXPECT_NE(asset_manager, asset_manager_2);
    EXPECT_TRUE(*asset_manager == *asset_manager_2);

    engine->UpdateAssetManager(asset_manager);
    EXPECT_EQ(engine->GetAssetManager(), asset_manager);

    engine->UpdateAssetManager(asset_manager_2);
    // Didn't change because they're equivalent.
    EXPECT_EQ(engine->GetAssetManager(), asset_manager);
  });
}

// The warm up frame should work if only some of the registered views are
// included.
//
// This test also verifies that the warm up frame can render multiple views.
TEST_F(EngineTest, AnimatorSubmitPartialViewsForWarmUp) {
  MockAnimatorDelegate animator_delegate;
  std::unique_ptr<EngineContext> engine_context;

  std::shared_ptr<PlatformMessageHandler> platform_message_handler =
      std::make_shared<MockPlatformMessageHandler>();
  EXPECT_CALL(delegate_, GetPlatformMessageHandler)
      .WillOnce(ReturnRef(platform_message_handler));

  fml::AutoResetWaitableEvent continuation_ready_latch;
  fml::AutoResetWaitableEvent draw_latch;
  EXPECT_CALL(animator_delegate, OnAnimatorDraw)
      .WillOnce(
          Invoke([&draw_latch](const std::shared_ptr<FramePipeline>& pipeline) {
            auto status =
                pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
                  EXPECT_EQ(item->layer_tree_tasks.size(), 2u);
                  EXPECT_EQ(item->layer_tree_tasks[0]->view_id, 1);
                  EXPECT_EQ(item->layer_tree_tasks[1]->view_id, 2);
                });
            EXPECT_EQ(status, PipelineConsumeResult::Done);
            draw_latch.Signal();
          }));
  EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
      .WillRepeatedly(
          Invoke([&engine_context, &continuation_ready_latch](
                     fml::TimePoint frame_target_time, uint64_t frame_number) {
            continuation_ready_latch.Signal();
            engine_context->EngineTaskSync([&](Engine& engine) {
              engine.BeginFrame(frame_target_time, frame_number);
            });
          }));

  std::unique_ptr<Animator> animator;
  PostSync(task_runners_.GetUITaskRunner(),
           [&animator, &animator_delegate, &task_runners = task_runners_] {
             animator = std::make_unique<Animator>(
                 animator_delegate, task_runners,
                 static_cast<std::unique_ptr<VsyncWaiter>>(
                     std::make_unique<testing::ConstantFiringVsyncWaiter>(
                         task_runners)));
           });

  engine_context = EngineContext::Create(delegate_, settings_, task_runners_,
                                         std::move(animator));

  engine_context->EngineTaskSync([](Engine& engine) {
    // Schedule a frame to make the animator create a continuation.
    engine.ScheduleFrame(true);
    // Add multiple views.
    engine.AddView(0, ViewportMetrics{1, 10, 10, 22, 0});
    engine.AddView(1, ViewportMetrics{1, 10, 10, 22, 0});
    engine.AddView(2, ViewportMetrics{1, 10, 10, 22, 0});
  });

  continuation_ready_latch.Wait();

  auto configuration = RunConfiguration::InferFromSettings(settings_);
  configuration.SetEntrypoint("renderWarmUpView1and2");
  engine_context->Run(std::move(configuration));

  draw_latch.Wait();
}

}  // namespace flutter
