// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/ffi_callback_metadata.h"

#include <memory>
#include <thread>  // NOLINT(build/c++11)
#include <unordered_set>
#include <vector>

#include "include/dart_api.h"
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/ffi/callback.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/message_handler.h"
#include "vm/object.h"
#include "vm/port.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"

namespace dart {

FunctionPtr CreateTestFunction(FfiCallbackKind kind) {
  const auto& ffi_lib = Library::Handle(Library::FfiLibrary());
  const auto& ffi_void = Class::Handle(ffi_lib.LookupClass(Symbols::FfiVoid()));
  const auto& ffi_void_type =
      Type::Handle(Type::NewNonParameterizedType(ffi_void));

  auto* thread = Thread::Current();
  const char* kScriptChars =
      R"(
      void testFunction() {
      }
      )";
  Dart_Handle library;
  {
    TransitionVMToNative transition(thread);
    library = TestCase::LoadTestScript(kScriptChars, nullptr);
    EXPECT_VALID(library);
  }

  const auto& lib =
      Library::Handle(Library::RawCast(Api::UnwrapHandle(library)));
  EXPECT(ClassFinalizer::ProcessPendingClasses());
  const auto& cls = Class::Handle(lib.toplevel_class());
  EXPECT(!cls.IsNull());
  const auto& error = cls.EnsureIsFinalized(thread);
  EXPECT(error == Error::null());

  auto& function_name = String::Handle(String::New("testFunction"));
  const auto& func = Function::Handle(cls.LookupStaticFunction(function_name));
  EXPECT(!func.IsNull());

  FunctionType& signature = FunctionType::Handle(FunctionType::New());
  signature.set_result_type(ffi_void_type);
  signature.SetIsFinalized();
  signature ^= signature.Canonicalize(thread);

  const auto& callback = Function::Handle(compiler::ffi::NativeCallbackFunction(
      signature, func, Instance::Handle(Instance::null()), kind));

  const auto& result = Object::Handle(
      thread->zone(), Compiler::CompileFunction(thread, callback));
  EXPECT(!result.IsError());

  return callback.ptr();
}

class FakeMessageHandler : public MessageHandler {
 public:
  MessageStatus HandleMessage(std::unique_ptr<Message> message) override {
    return MessageHandler::kOK;
  }
};

VM_UNIT_TEST_CASE(FfiCallbackMetadata_CreateSyncFfiCallback) {
  auto* fcm = FfiCallbackMetadata::Instance();
  FfiCallbackMetadata::Trampoline tramp1 = 0;
  FfiCallbackMetadata::Trampoline tramp2 = 0;

  {
    TestIsolateScope isolate_scope;
    Thread* thread = Thread::Current();
    Isolate* isolate = thread->isolate();
    ASSERT(isolate == isolate_scope.isolate());
    TransitionNativeToVM transition(thread);
    StackZone stack_zone(thread);
    HandleScope handle_scope(thread);

    auto* zone = thread->zone();

    const auto& func = Function::Handle(
        CreateTestFunction(FfiCallbackKind::kIsolateLocalStaticCallback));
    const auto& code = Code::Handle(func.EnsureHasCode());
    EXPECT(!code.IsNull());

    tramp1 = isolate->CreateIsolateLocalFfiCallback(
        zone, func, Closure::Handle(Closure::null()), false);
    EXPECT_NE(tramp1, 0u);

    {
      FfiCallbackMetadata::Metadata m1 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp1);
      EXPECT(m1.IsLive());
      EXPECT_EQ(m1.target_isolate(), isolate);
      EXPECT_EQ(m1.target_entry_point(), code.EntryPoint());
      EXPECT_EQ(m1.closure_handle(), nullptr);
      EXPECT_EQ(static_cast<int>(m1.trampoline_type()),
                static_cast<int>(FfiCallbackMetadata::TrampolineType::kSync));

      // head -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e1);
      EXPECT_EQ(e1->list_prev(), nullptr);
      EXPECT_EQ(e1->list_next(), nullptr);
    }

    tramp2 = isolate->CreateIsolateLocalFfiCallback(
        zone, func, Closure::Handle(Closure::null()), false);
    EXPECT_NE(tramp2, 0u);
    EXPECT_NE(tramp2, tramp1);

    {
      FfiCallbackMetadata::Metadata m2 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp2);
      EXPECT(m2.IsLive());
      EXPECT_EQ(m2.target_isolate(), isolate);
      EXPECT_EQ(m2.target_entry_point(), code.EntryPoint());
      EXPECT_EQ(m2.closure_handle(), nullptr);
      EXPECT_EQ(static_cast<int>(m2.trampoline_type()),
                static_cast<int>(FfiCallbackMetadata::TrampolineType::kSync));
    }

    {
      // head -> tramp2 -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      auto* e2 = fcm->MetadataEntryOfTrampoline(tramp2);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e2);
      EXPECT_EQ(e2->list_prev(), nullptr);
      EXPECT_EQ(e2->list_next(), e1);
      EXPECT_EQ(e1->list_prev(), e2);
      EXPECT_EQ(e1->list_next(), nullptr);
    }

    {
      isolate->DeleteFfiCallback(tramp1);
      FfiCallbackMetadata::Metadata m1 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp1);
      EXPECT(!m1.IsLive());

      // head -> tramp2
      auto* e2 = fcm->MetadataEntryOfTrampoline(tramp2);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e2);
      EXPECT_EQ(e2->list_prev(), nullptr);
      EXPECT_EQ(e2->list_next(), nullptr);
    }
  }

  {
    // Isolate has shut down, so all callbacks should be deleted.
    FfiCallbackMetadata::Metadata m1 =
        fcm->LookupMetadataForTrampolineUnlocked(tramp1);
    EXPECT(!m1.IsLive());

    FfiCallbackMetadata::Metadata m2 =
        fcm->LookupMetadataForTrampolineUnlocked(tramp2);
    EXPECT(!m2.IsLive());
  }
}

VM_UNIT_TEST_CASE(FfiCallbackMetadata_CreateAsyncFfiCallback) {
  auto* fcm = FfiCallbackMetadata::Instance();
  FfiCallbackMetadata::Trampoline tramp1 = 0;
  FfiCallbackMetadata::Trampoline tramp2 = 0;

  {
    TestIsolateScope isolate_scope;
    Thread* thread = Thread::Current();
    Isolate* isolate = thread->isolate();
    ASSERT(thread->isolate() == isolate_scope.isolate());
    TransitionNativeToVM transition(thread);
    StackZone stack_zone(thread);
    HandleScope handle_scope(thread);

    auto* zone = thread->zone();

    const Function& func =
        Function::Handle(CreateTestFunction(FfiCallbackKind::kAsyncCallback));
    const Code& code = Code::Handle(func.EnsureHasCode());
    EXPECT(!code.IsNull());

    EXPECT_EQ(isolate->ffi_callback_list_head(), nullptr);

    auto port1 = PortMap::CreatePort(new FakeMessageHandler());
    tramp1 = isolate->CreateAsyncFfiCallback(zone, func, port1);
    EXPECT_NE(tramp1, 0u);

    {
      FfiCallbackMetadata::Metadata m1 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp1);
      EXPECT(m1.IsLive());
      EXPECT_EQ(m1.target_isolate(), isolate);
      EXPECT_EQ(m1.target_entry_point(), code.EntryPoint());
      EXPECT_EQ(m1.send_port(), port1);
      EXPECT_EQ(static_cast<int>(m1.trampoline_type()),
                static_cast<int>(FfiCallbackMetadata::TrampolineType::kAsync));

      // head -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e1);
      EXPECT_EQ(e1->list_prev(), nullptr);
      EXPECT_EQ(e1->list_next(), nullptr);
    }

    auto port2 = PortMap::CreatePort(new FakeMessageHandler());
    tramp2 = isolate->CreateAsyncFfiCallback(zone, func, port2);
    EXPECT_NE(tramp2, 0u);
    EXPECT_NE(tramp2, tramp1);

    {
      FfiCallbackMetadata::Metadata m2 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp2);
      EXPECT(m2.IsLive());
      EXPECT_EQ(m2.target_isolate(), isolate);
      EXPECT_EQ(m2.target_entry_point(), code.EntryPoint());
      EXPECT_EQ(m2.send_port(), port2);
      EXPECT_EQ(static_cast<int>(m2.trampoline_type()),
                static_cast<int>(FfiCallbackMetadata::TrampolineType::kAsync));
    }

    {
      // head -> tramp2 -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      auto* e2 = fcm->MetadataEntryOfTrampoline(tramp2);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e2);
      EXPECT_EQ(e2->list_prev(), nullptr);
      EXPECT_EQ(e2->list_next(), e1);
      EXPECT_EQ(e1->list_prev(), e2);
      EXPECT_EQ(e1->list_next(), nullptr);
    }

    {
      isolate->DeleteFfiCallback(tramp2);
      FfiCallbackMetadata::Metadata m2 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp2);
      EXPECT(!m2.IsLive());

      // head -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e1);
      EXPECT_EQ(e1->list_prev(), nullptr);
      EXPECT_EQ(e1->list_next(), nullptr);
    }
  }

  {
    // Isolate has shut down, so all callbacks should be deleted.
    FfiCallbackMetadata::Metadata m1 =
        fcm->LookupMetadataForTrampolineUnlocked(tramp1);
    EXPECT(!m1.IsLive());

    FfiCallbackMetadata::Metadata m2 =
        fcm->LookupMetadataForTrampolineUnlocked(tramp2);
    EXPECT(!m2.IsLive());
  }
}

VM_UNIT_TEST_CASE(FfiCallbackMetadata_CreateIsolateLocalFfiCallback) {
  auto* fcm = FfiCallbackMetadata::Instance();
  FfiCallbackMetadata::Trampoline tramp1 = 0;
  FfiCallbackMetadata::Trampoline tramp2 = 0;

  {
    TestIsolateScope isolate_scope;
    Thread* thread = Thread::Current();
    Isolate* isolate = thread->isolate();
    ASSERT(thread->isolate() == isolate_scope.isolate());
    TransitionNativeToVM transition(thread);
    StackZone stack_zone(thread);
    HandleScope handle_scope(thread);

    auto* zone = thread->zone();

    const Function& func = Function::Handle(
        CreateTestFunction(FfiCallbackKind::kIsolateLocalClosureCallback));
    const Code& code = Code::Handle(func.EnsureHasCode());
    EXPECT(!code.IsNull());

    // Using a FfiCallbackKind::kSync function as a dummy closure.
    const Function& closure_func = Function::Handle(
        CreateTestFunction(FfiCallbackKind::kIsolateLocalStaticCallback));
    const Context& context = Context::Handle(Context::null());
    const Closure& closure1 = Closure::Handle(
        Closure::New(Object::null_type_arguments(),
                     Object::null_type_arguments(), closure_func, context));

    EXPECT_EQ(isolate->ffi_callback_list_head(), nullptr);

    tramp1 = isolate->CreateIsolateLocalFfiCallback(zone, func, closure1, true);
    EXPECT_NE(tramp1, 0u);

    {
      FfiCallbackMetadata::Metadata m1 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp1);
      EXPECT(m1.IsLive());
      EXPECT_EQ(m1.target_isolate(), isolate);
      EXPECT_EQ(m1.target_entry_point(), code.EntryPoint());
      EXPECT_EQ(m1.closure_handle()->ptr(), closure1.ptr());
      EXPECT_EQ(static_cast<int>(m1.trampoline_type()),
                static_cast<int>(FfiCallbackMetadata::TrampolineType::kSync));

      // head -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e1);
      EXPECT_EQ(e1->list_prev(), nullptr);
      EXPECT_EQ(e1->list_next(), nullptr);
    }

    const Closure& closure2 = Closure::Handle(
        Closure::New(Object::null_type_arguments(),
                     Object::null_type_arguments(), closure_func, context));
    tramp2 = isolate->CreateIsolateLocalFfiCallback(zone, func, closure2, true);
    EXPECT_NE(tramp2, 0u);
    EXPECT_NE(tramp2, tramp1);

    {
      FfiCallbackMetadata::Metadata m2 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp2);
      EXPECT(m2.IsLive());
      EXPECT_EQ(m2.target_isolate(), isolate);
      EXPECT_EQ(m2.target_entry_point(), code.EntryPoint());
      EXPECT_EQ(m2.closure_handle()->ptr(), closure2.ptr());
      EXPECT_EQ(static_cast<int>(m2.trampoline_type()),
                static_cast<int>(FfiCallbackMetadata::TrampolineType::kSync));
    }

    {
      // head -> tramp2 -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      auto* e2 = fcm->MetadataEntryOfTrampoline(tramp2);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e2);
      EXPECT_EQ(e2->list_prev(), nullptr);
      EXPECT_EQ(e2->list_next(), e1);
      EXPECT_EQ(e1->list_prev(), e2);
      EXPECT_EQ(e1->list_next(), nullptr);
    }

    {
      isolate->DeleteFfiCallback(tramp2);
      FfiCallbackMetadata::Metadata m2 =
          fcm->LookupMetadataForTrampolineUnlocked(tramp2);
      EXPECT(!m2.IsLive());

      // head -> tramp1
      auto* e1 = fcm->MetadataEntryOfTrampoline(tramp1);
      EXPECT_EQ(isolate->ffi_callback_list_head(), e1);
      EXPECT_EQ(e1->list_prev(), nullptr);
      EXPECT_EQ(e1->list_next(), nullptr);
    }
  }

  {
    // Isolate has shut down, so all callbacks should be deleted.
    FfiCallbackMetadata::Metadata m1 =
        fcm->LookupMetadataForTrampolineUnlocked(tramp1);
    EXPECT(!m1.IsLive());

    FfiCallbackMetadata::Metadata m2 =
        fcm->LookupMetadataForTrampolineUnlocked(tramp2);
    EXPECT(!m2.IsLive());
  }
}

ISOLATE_UNIT_TEST_CASE(FfiCallbackMetadata_TrampolineRecycling) {
  Isolate* isolate = thread->isolate();
  auto* zone = thread->zone();
  auto* fcm = FfiCallbackMetadata::Instance();

  const Function& func =
      Function::Handle(CreateTestFunction(FfiCallbackKind::kAsyncCallback));
  const Code& code = Code::Handle(func.EnsureHasCode());
  EXPECT(!code.IsNull());

  auto port = PortMap::CreatePort(new FakeMessageHandler());
  FfiCallbackMetadata::MetadataEntry* list_head = nullptr;

  // Allocate and free one callback at a time, and verify that we don't reuse
  // them. Allocate enough that the whole page fills up with dead trampolines.
  std::vector<FfiCallbackMetadata::Trampoline> allocation_order;
  std::unordered_set<FfiCallbackMetadata::Trampoline> allocated;
  const intptr_t trampolines_per_page =
      FfiCallbackMetadata::NumCallbackTrampolinesPerPage();
  for (intptr_t i = 0; i < trampolines_per_page; ++i) {
    auto tramp =
        fcm->CreateAsyncFfiCallback(isolate, zone, func, port, &list_head);
    EXPECT_EQ(allocated.count(tramp), 0u);
    allocation_order.push_back(tramp);
    allocated.insert(tramp);
    fcm->DeleteCallback(tramp, &list_head);
  }

  // Now  as we continue allocating and freeing, we start reusing them, in the
  // same allocation order as before.
  for (intptr_t i = 0; i < trampolines_per_page; ++i) {
    auto tramp =
        fcm->CreateAsyncFfiCallback(isolate, zone, func, port, &list_head);
    EXPECT_EQ(allocated.count(tramp), 1u);
    EXPECT_EQ(allocation_order[i], tramp);
    fcm->DeleteCallback(tramp, &list_head);
  }

  // Now allocate enough to fill the page without freeing them. Again they
  // should come out in the same order.
  for (intptr_t i = 0; i < trampolines_per_page; ++i) {
    auto tramp =
        fcm->CreateAsyncFfiCallback(isolate, zone, func, port, &list_head);
    EXPECT_EQ(allocated.count(tramp), 1u);
    EXPECT_EQ(allocation_order[i], tramp);
  }

  // Now that the page is full, we should allocate a new page and see new
  // trampolines we haven't seen before.
  for (intptr_t i = 0; i < 3 * trampolines_per_page; ++i) {
    auto tramp =
        fcm->CreateAsyncFfiCallback(isolate, zone, func, port, &list_head);
    EXPECT_EQ(allocated.count(tramp), 0u);
  }
}

VM_UNIT_TEST_CASE(FfiCallbackMetadata_DeleteTrampolines) {
  static constexpr int kCreations = 1000;
  static constexpr int kDeletions = 100;

  TestIsolateScope isolate_scope;
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate == isolate_scope.isolate());
  TransitionNativeToVM transition(thread);
  StackZone stack_zone(thread);
  HandleScope handle_scope(thread);

  auto* fcm = FfiCallbackMetadata::Instance();
  std::unordered_set<FfiCallbackMetadata::Trampoline> tramps;
  FfiCallbackMetadata::MetadataEntry* list_head = nullptr;

  const auto& sync_func = Function::Handle(
      CreateTestFunction(FfiCallbackKind::kIsolateLocalStaticCallback));
  const auto& sync_code = Code::Handle(sync_func.EnsureHasCode());
  EXPECT(!sync_code.IsNull());

  // Create some callbacks.
  for (int itr = 0; itr < kCreations; ++itr) {
    tramps.insert(fcm->CreateLocalFfiCallback(
        isolate, /*isolate_group=*/nullptr, thread->zone(), sync_func,
        Closure::Handle(Closure::null()), &list_head));
  }

  // Delete some of the callbacks.
  for (int itr = 0; itr < kDeletions; ++itr) {
    auto tramp = *tramps.begin();
    fcm->DeleteCallback(tramp, &list_head);
    tramps.erase(tramp);
  }

  // Verify all the callbacks.
  for (FfiCallbackMetadata::Trampoline tramp : tramps) {
    auto metadata = fcm->LookupMetadataForTrampolineUnlocked(tramp);
    EXPECT(metadata.IsLive());
    EXPECT_EQ(metadata.target_isolate(), isolate);
    EXPECT_EQ(static_cast<int>(metadata.trampoline_type()),
              static_cast<int>(FfiCallbackMetadata::TrampolineType::kSync));
    EXPECT_EQ(metadata.target_entry_point(), sync_code.EntryPoint());
  }

  // Verify the list of callbacks.
  uword list_length = 0;
  for (FfiCallbackMetadata::MetadataEntry* me = list_head; me != nullptr;) {
    ++list_length;
    auto tramp = fcm->TrampolineOfMetadataEntry(me);
    EXPECT(me->metadata()->IsLive());
    EXPECT_EQ(me->metadata()->target_isolate(), isolate);
    EXPECT_EQ(tramps.count(tramp), 1u);
    auto* next = me->list_next();
    auto* prev = me->list_prev();
    if (prev != nullptr) {
      EXPECT_EQ(prev->list_next(), me);
    } else {
      EXPECT_EQ(list_head, me);
    }
    if (next != nullptr) {
      EXPECT_EQ(next->list_prev(), me);
    }
    me = me->list_next();
  }
  EXPECT_EQ(list_length, tramps.size());

  // Delete all callbacks and verify they're destroyed.
  fcm->DeleteAllCallbacks(&list_head);
  EXPECT_EQ(list_head, nullptr);
  for (FfiCallbackMetadata::Trampoline tramp : tramps) {
    EXPECT(!fcm->LookupMetadataForTrampolineUnlocked(tramp).IsLive());
  }
}

static void RunBigRandomMultithreadedTest(uint64_t seed) {
  static constexpr int kIterations = 1000;

  TestIsolateScope isolate_scope;
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate == isolate_scope.isolate());
  TransitionNativeToVM transition(thread);
  StackZone stack_zone(thread);
  HandleScope handle_scope(thread);

  struct TrampolineWithPort {
    FfiCallbackMetadata::Trampoline tramp;
    Dart_Port port;
  };

  auto* fcm = FfiCallbackMetadata::Instance();
  Random random(seed);
  std::vector<TrampolineWithPort> tramps;
  std::unordered_set<FfiCallbackMetadata::Trampoline> tramp_set;
  FfiCallbackMetadata::MetadataEntry* list_head = nullptr;

  const Function& async_func =
      Function::Handle(CreateTestFunction(FfiCallbackKind::kAsyncCallback));
  const Code& async_code = Code::Handle(async_func.EnsureHasCode());
  EXPECT(!async_code.IsNull());
  const Function& sync_func = Function::Handle(
      CreateTestFunction(FfiCallbackKind::kIsolateLocalStaticCallback));
  const auto& sync_code = Code::Handle(sync_func.EnsureHasCode());
  EXPECT(!sync_code.IsNull());

  for (int itr = 0; itr < kIterations; ++itr) {
    // Do a random action:
    //  - Allocate a sync callback
    //  - Allocate an async callback
    //  - Delete a callback
    //  - Delete all the sync callbacks for an isolate

    if ((random.NextUInt32() % 100) == 0) {
      // 1% chance of deleting all the callbacks on the thread.
      fcm->DeleteAllCallbacks(&list_head);

      // It would be nice to verify that all the trampolines have been deleted,
      // but this is flaky because other threads can recycle these trampolines
      // before we finish checking all of them.
      tramps.clear();
      tramp_set.clear();
      EXPECT_EQ(list_head, nullptr);
    } else if (tramps.size() > 0 && (random.NextUInt32() % 4) == 0) {
      // 25% chance of deleting a callback.
      uint32_t r = random.NextUInt32() % tramps.size();
      auto tramp = tramps[r].tramp;
      fcm->DeleteCallback(tramp, &list_head);
      tramps[r] = tramps[tramps.size() - 1];
      tramps.pop_back();
      tramp_set.erase(tramp);
    } else {
      TrampolineWithPort tramp;
      if ((random.NextUInt32() % 2) == 0) {
        // 50% chance of creating a sync callback.
        tramp.port = ILLEGAL_PORT;
        tramp.tramp = fcm->CreateLocalFfiCallback(
            isolate, /*isolate_group=*/nullptr, thread->zone(), sync_func,
            Closure::Handle(Closure::null()), &list_head);
      } else {
        // 50% chance of creating an async callback.
        tramp.port = PortMap::CreatePort(new FakeMessageHandler());
        tramp.tramp = fcm->CreateAsyncFfiCallback(
            isolate, thread->zone(), async_func, tramp.port, &list_head);
      }
      tramps.push_back(tramp);
      tramp_set.insert(tramp.tramp);
    }

    // Verify all the callbacks.
    for (const auto& tramp : tramps) {
      auto metadata = fcm->LookupMetadataForTrampolineUnlocked(tramp.tramp);
      EXPECT(metadata.IsLive());
      EXPECT_EQ(metadata.target_isolate(), isolate);
      if (metadata.trampoline_type() ==
          FfiCallbackMetadata::TrampolineType::kSync) {
        EXPECT_EQ(metadata.closure_handle(), nullptr);
        EXPECT_EQ(metadata.target_entry_point(), sync_code.EntryPoint());
      } else {
        EXPECT_EQ(metadata.send_port(), tramp.port);
        EXPECT_EQ(metadata.target_entry_point(), async_code.EntryPoint());
      }
    }

    // Verify the isolate's list of callbacks.
    uword list_length = 0;
    for (FfiCallbackMetadata::MetadataEntry* me = list_head; me != nullptr;) {
      ++list_length;
      auto tramp = fcm->TrampolineOfMetadataEntry(me);
      EXPECT(me->metadata()->IsLive());
      EXPECT_EQ(me->metadata()->target_isolate(), isolate);
      EXPECT_EQ(tramp_set.count(tramp), 1u);
      me = me->list_next();
    }
    EXPECT_EQ(list_length, tramps.size());
    EXPECT_EQ(list_length, tramp_set.size());
  }

  // Delete all remaining callbacks.
  fcm->DeleteAllCallbacks(&list_head);
  EXPECT_EQ(list_head, nullptr);
}

ISOLATE_UNIT_TEST_CASE(FfiCallbackMetadata_BigRandomMultithreadedTest) {
  static constexpr int kThreads = 5;

  std::vector<std::thread> threads;

  Random random;
  for (int i = 0; i < kThreads; ++i) {
    threads.push_back(
        std::thread(RunBigRandomMultithreadedTest, random.NextUInt64()));
  }

  for (auto& thread : threads) {
    thread.join();
  }
}

}  // namespace dart
