// 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/testing/dart_isolate_runner.h"
#include "flutter/testing/fixture_test.h"

namespace flutter {
namespace testing {

class DartWeakPersistentHandle : public FixtureTest {
 public:
  DartWeakPersistentHandle()
      : settings_(CreateSettingsForFixture()),
        vm_(DartVMRef::Create(settings_)) {}

  ~DartWeakPersistentHandle() = default;

  [[nodiscard]] bool RunWithEntrypoint(const std::string& entrypoint) {
    if (running_isolate_) {
      return false;
    }
    auto thread = CreateNewThread();
    TaskRunners single_threaded_task_runner(GetCurrentTestName(), thread,
                                            thread, thread, thread);
    auto isolate =
        RunDartCodeInIsolate(vm_, settings_, single_threaded_task_runner,
                             entrypoint, {}, GetFixturesPath());
    if (!isolate || isolate->get()->GetPhase() != DartIsolate::Phase::Running) {
      return false;
    }

    running_isolate_ = std::move(isolate);
    return true;
  }

  [[nodiscard]] bool RunInIsolateScope(std::function<bool(void)> closure) {
    return running_isolate_->RunInIsolateScope(closure);
  }

 private:
  Settings settings_;
  DartVMRef vm_;
  std::unique_ptr<AutoIsolateShutdown> running_isolate_;
  FML_DISALLOW_COPY_AND_ASSIGN(DartWeakPersistentHandle);
};

void NopFinalizer(void* isolate_callback_data, void* peer) {}

TEST_F(DartWeakPersistentHandle, ClearImmediately) {
  auto weak_persistent_value = tonic::DartWeakPersistentValue();

  fml::AutoResetWaitableEvent event;

  AddNativeCallback(
      "GiveObjectToNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
        auto handle = Dart_GetNativeArgument(args, 0);

        auto dart_state = tonic::DartState::Current();
        ASSERT_TRUE(dart_state);
        ASSERT_TRUE(tonic::DartState::Current());
        weak_persistent_value.Set(dart_state, handle, nullptr, 0, NopFinalizer);

        weak_persistent_value.Clear();

        event.Signal();
      }));

  ASSERT_TRUE(RunWithEntrypoint("callGiveObjectToNative"));

  event.Wait();
}

TEST_F(DartWeakPersistentHandle, ClearLaterCc) {
  auto weak_persistent_value = tonic::DartWeakPersistentValue();

  fml::AutoResetWaitableEvent event;

  AddNativeCallback(
      "GiveObjectToNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
        auto handle = Dart_GetNativeArgument(args, 0);

        auto dart_state = tonic::DartState::Current();
        ASSERT_TRUE(dart_state);
        ASSERT_TRUE(tonic::DartState::Current());
        weak_persistent_value.Set(dart_state, handle, nullptr, 0, NopFinalizer);

        // Do not clear handle immediately.

        event.Signal();
      }));

  ASSERT_TRUE(RunWithEntrypoint("callGiveObjectToNative"));

  event.Wait();

  ASSERT_TRUE(RunInIsolateScope([&weak_persistent_value]() -> bool {
    // Clear on initiative of native.
    weak_persistent_value.Clear();
    return true;
  }));
}

TEST_F(DartWeakPersistentHandle, ClearLaterDart) {
  auto weak_persistent_value = tonic::DartWeakPersistentValue();

  fml::AutoResetWaitableEvent event;

  AddNativeCallback(
      "GiveObjectToNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
        auto handle = Dart_GetNativeArgument(args, 0);

        auto dart_state = tonic::DartState::Current();
        ASSERT_TRUE(dart_state);
        ASSERT_TRUE(tonic::DartState::Current());
        weak_persistent_value.Set(dart_state, handle, nullptr, 0, NopFinalizer);

        // Do not clear handle immediately.
      }));

  AddNativeCallback("SignalDone",
                    CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
                      // Clear on initiative of Dart.
                      weak_persistent_value.Clear();

                      event.Signal();
                    }));

  ASSERT_TRUE(RunWithEntrypoint("testClearLater"));

  event.Wait();
}

// Handle outside the test body scope so it survives until isolate shutdown.
tonic::DartWeakPersistentValue global_weak_persistent_value =
    tonic::DartWeakPersistentValue();

TEST_F(DartWeakPersistentHandle, ClearOnShutdown) {
  fml::AutoResetWaitableEvent event;

  AddNativeCallback("GiveObjectToNative",
                    CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
                      auto handle = Dart_GetNativeArgument(args, 0);

                      auto dart_state = tonic::DartState::Current();
                      ASSERT_TRUE(dart_state);
                      ASSERT_TRUE(tonic::DartState::Current());

                      // The test is repeated, ensure the global var is
                      // cleared before use.
                      global_weak_persistent_value.Clear();

                      global_weak_persistent_value.Set(
                          dart_state, handle, nullptr, 0, NopFinalizer);

                      // Do not clear handle, so it is cleared on shutdown.

                      event.Signal();
                    }));

  ASSERT_TRUE(RunWithEntrypoint("callGiveObjectToNative"));

  event.Wait();
}

}  // namespace testing
}  // namespace flutter
